summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineOpenGL
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2015-10-21 03:46:28 +0000
committerEgor Yusov <egor.yusov@gmail.com>2015-10-21 03:46:28 +0000
commit9ccee73baca0fd7ecb95c90cb983133b737c6c55 (patch)
tree66fea1e6521df31727431520fe3c1ead1896bc5d /Graphics/GraphicsEngineOpenGL
downloadDiligentCore-9ccee73baca0fd7ecb95c90cb983133b737c6c55.tar.gz
DiligentCore-9ccee73baca0fd7ecb95c90cb983133b737c6c55.zip
Release v1.0.0
Diffstat (limited to 'Graphics/GraphicsEngineOpenGL')
-rw-r--r--Graphics/GraphicsEngineOpenGL/build/Windows/Android/gcc_Debug.h199
-rw-r--r--Graphics/GraphicsEngineOpenGL/build/Windows/Android/gcc_Release.h380
-rw-r--r--Graphics/GraphicsEngineOpenGL/build/Windows/EngineRoot.props22
-rw-r--r--Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL-Debug.vgdbsettings76
-rw-r--r--Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL-Release.vgdbsettings76
-rw-r--r--Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL.props10
-rw-r--r--Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL.vcxproj538
-rw-r--r--Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL.vcxproj.filters306
-rw-r--r--Graphics/GraphicsEngineOpenGL/build/Windows/jni/Android.mk68
-rw-r--r--Graphics/GraphicsEngineOpenGL/build/Windows/jni/Application.mk7
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/AsyncWritableResource.h65
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/BlendStateGLImpl.h47
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h69
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/BufferViewGLImpl.h56
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/DSStateGLImpl.h46
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h97
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/FBOCache.h92
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLContextAndroid.h83
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLContextState.h212
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLContextWindows.h49
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLObjectWrapper.h195
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLProgram.h114
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions.h957
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions_inc.h957
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLStubs.h1051
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.h241
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/HLSL2GLSLConverter.h424
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/ProgramPipelineCache.h102
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/RasterizerStateGLImpl.h46
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLESImpl.h45
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h131
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/SamplerGLImpl.h52
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h105
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/SwapChainGLImpl.h50
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/TexRegionRender.h66
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/Texture1DArray_OGL.h48
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/Texture1D_OGL.h48
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/Texture2DArray_OGL.h48
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/Texture2D_OGL.h48
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/Texture3D_OGL.h48
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h83
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/TextureViewGLImpl.h60
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/VAOCache.h103
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/VertexDescGLImpl.h50
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/pch.h96
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/BaseInterfacesGL.h48
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/BlendStateGL.h45
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/BufferGL.h45
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/BufferViewGL.h45
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/DepthStencilStateGL.h45
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/DeviceContextGL.h45
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/RasterizerStateGL.h45
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/RenderDeviceFactoryOpenGL.h106
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGL.h46
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGLES.h51
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/SamplerGL.h45
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/ShaderGL.h45
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/SwapChainGL.h44
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/TextureGL.h47
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/TextureViewGL.h46
-rw-r--r--Graphics/GraphicsEngineOpenGL/interface/VertexDescriptionGL.h45
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/BlendStateGLImpl.cpp42
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp311
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp60
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/DLLMain.cpp49
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/DSStateGLImpl.cpp43
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp889
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/FBOCache.cpp280
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/GLContextAndroid.cpp399
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/GLContextState.cpp647
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/GLContextWindows.cpp233
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/GLObjectWrapper.cpp37
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/GLProgram.cpp305
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/GLStubs.cpp266
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/GLTypeConversions.cpp602
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/GraphicsEngineOpenGL.def2
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/HLSL2GLSLConverter.cpp3261
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/ProgramPipelineCache.cpp164
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/RasterizerStateGLImpl.cpp43
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/RenderDeviceFactoryOpenGL.cpp110
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLESImpl.cpp51
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp631
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/SamplerGLImpl.cpp124
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp342
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp71
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp264
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/Texture1DArray_OGL.cpp156
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/Texture1D_OGL.cpp135
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/Texture2DArray_OGL.cpp217
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/Texture2D_OGL.cpp197
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/Texture3D_OGL.cpp171
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp433
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/TextureViewGLImpl.cpp84
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp220
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/VertexDescGLImpl.cpp45
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/pch.cpp31
96 files changed, 19374 insertions, 0 deletions
diff --git a/Graphics/GraphicsEngineOpenGL/build/Windows/Android/gcc_Debug.h b/Graphics/GraphicsEngineOpenGL/build/Windows/Android/gcc_Debug.h
new file mode 100644
index 00000000..b46f53e0
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/build/Windows/Android/gcc_Debug.h
@@ -0,0 +1,199 @@
+/*
+ This file is only used by IntelliSense (VisualStudio code suggestion system)
+ DO NOT INCLUDE THIS FILE FROM YOUR ACTUAL SOURCE FILES.
+ This file lists the preprocessor macros extracted from your GCC.
+ It is needed for IntelliSense to parse other header files correctly.
+*/
+#ifdef _MSC_VER
+#define _GNU_SOURCE 1
+#define __ANDROID__ 1
+#define __APCS_32__ 1
+#define __ARMEL__ 1
+#define __ARM_ARCH 7
+#define __ARM_ARCH_7A__ 1
+#define __ARM_ARCH_PROFILE A
+#define __ARM_EABI__ 1
+#define __ARM_PCS 1
+#define __ARM_VFPV3__ 1
+#define __ATOMIC_ACQUIRE 2
+#define __ATOMIC_ACQ_REL 4
+#define __ATOMIC_CONSUME 1
+#define __ATOMIC_RELAXED 0
+#define __ATOMIC_RELEASE 3
+#define __ATOMIC_SEQ_CST 5
+#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+#define __CHAR16_TYPE__ unsigned short
+#define __CHAR32_TYPE__ unsigned int
+#define __CHAR_BIT__ 8
+#define __CHAR_UNSIGNED__ 1
+#define __CONSTANT_CFSTRINGS__ 1
+#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+#define __DBL_DIG__ 15
+#define __DBL_EPSILON__ 2.2204460492503131e-16
+#define __DBL_HAS_DENORM__ 1
+#define __DBL_HAS_INFINITY__ 1
+#define __DBL_HAS_QUIET_NAN__ 1
+#define __DBL_MANT_DIG__ 53
+#define __DBL_MAX_10_EXP__ 308
+#define __DBL_MAX_EXP__ 1024
+#define __DBL_MAX__ 1.7976931348623157e+308
+#define __DBL_MIN_10_EXP__ (-307)
+#define __DBL_MIN_EXP__ (-1021)
+#define __DBL_MIN__ 2.2250738585072014e-308
+#define __DECIMAL_DIG__ 17
+#define __DEPRECATED 1
+#define __ELF__ 1
+#define __EXCEPTIONS 1
+#define __FINITE_MATH_ONLY__ 0
+#define __FLT_DENORM_MIN__ 1.40129846e-45F
+#define __FLT_DIG__ 6
+#define __FLT_EPSILON__ 1.19209290e-7F
+#define __FLT_EVAL_METHOD__ 0
+#define __FLT_HAS_DENORM__ 1
+#define __FLT_HAS_INFINITY__ 1
+#define __FLT_HAS_QUIET_NAN__ 1
+#define __FLT_MANT_DIG__ 24
+#define __FLT_MAX_10_EXP__ 38
+#define __FLT_MAX_EXP__ 128
+#define __FLT_MAX__ 3.40282347e+38F
+#define __FLT_MIN_10_EXP__ (-37)
+#define __FLT_MIN_EXP__ (-125)
+#define __FLT_MIN__ 1.17549435e-38F
+#define __FLT_RADIX__ 2
+#define __GCC_ATOMIC_BOOL_LOCK_FREE 2
+#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
+#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
+#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
+#define __GCC_ATOMIC_INT_LOCK_FREE 2
+#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
+#define __GCC_ATOMIC_LONG_LOCK_FREE 2
+#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
+#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
+#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
+#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
+#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
+#define __GNUC_GNU_INLINE__ 1
+#define __GNUC_MINOR__ 2
+#define __GNUC_PATCHLEVEL__ 1
+#define __GNUC__ 4
+#define __GNUG__ 4
+#define __GXX_ABI_VERSION 1002
+#define __GXX_EXPERIMENTAL_CXX0X__ 1
+#define __GXX_RTTI 1
+#define __GXX_WEAK__ 1
+#define __INT16_TYPE__ short
+#define __INT32_TYPE__ int
+#define __INT64_C_SUFFIX__ LL
+#define __INT64_TYPE__ long long int
+#define __INT8_TYPE__ char
+#define __INTMAX_MAX__ 9223372036854775807LL
+#define __INTMAX_TYPE__ long long int
+#define __INTMAX_WIDTH__ 64
+#define __INTPTR_TYPE__ long int
+#define __INTPTR_WIDTH__ 32
+#define __INT_MAX__ 2147483647
+#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
+#define __LDBL_DIG__ 15
+#define __LDBL_EPSILON__ 2.2204460492503131e-16L
+#define __LDBL_HAS_DENORM__ 1
+#define __LDBL_HAS_INFINITY__ 1
+#define __LDBL_HAS_QUIET_NAN__ 1
+#define __LDBL_MANT_DIG__ 53
+#define __LDBL_MAX_10_EXP__ 308
+#define __LDBL_MAX_EXP__ 1024
+#define __LDBL_MAX__ 1.7976931348623157e+308L
+#define __LDBL_MIN_10_EXP__ (-307)
+#define __LDBL_MIN_EXP__ (-1021)
+#define __LDBL_MIN__ 2.2250738585072014e-308L
+#define __LITTLE_ENDIAN__ 1
+#define __LONG_LONG_MAX__ 9223372036854775807LL
+#define __LONG_MAX__ 2147483647L
+#define __NO_INLINE__ 1
+#define __ORDER_BIG_ENDIAN__ 4321
+#define __ORDER_LITTLE_ENDIAN__ 1234
+#define __ORDER_PDP_ENDIAN__ 3412
+#define __PIC__ 1
+#define __POINTER_WIDTH__ 32
+#define __PRAGMA_REDEFINE_EXTNAME 1
+#define __PTRDIFF_TYPE__ int
+#define __PTRDIFF_WIDTH__ 32
+#define __REGISTER_PREFIX__
+#define __SCHAR_MAX__ 127
+#define __SHRT_MAX__ 32767
+#define __SIG_ATOMIC_WIDTH__ 32
+#define __SIZEOF_DOUBLE__ 8
+#define __SIZEOF_FLOAT__ 4
+#define __SIZEOF_INT__ 4
+#define __SIZEOF_LONG_DOUBLE__ 8
+#define __SIZEOF_LONG_LONG__ 8
+#define __SIZEOF_LONG__ 4
+#define __SIZEOF_POINTER__ 4
+#define __SIZEOF_PTRDIFF_T__ 4
+#define __SIZEOF_SHORT__ 2
+#define __SIZEOF_SIZE_T__ 4
+#define __SIZEOF_WCHAR_T__ 4
+#define __SIZEOF_WINT_T__ 4
+#define __SIZE_MAX__ 4294967295U
+#define __SIZE_TYPE__ unsigned int
+#define __SIZE_WIDTH__ 32
+#define __SSP__ 1
+#define __STDC_HOSTED__ 1
+#define __STDC_UTF_16__ 1
+#define __STDC_UTF_32__ 1
+#define __STDC__ 1
+#define __STRICT_ANSI__ 1
+#define __THUMB_INTERWORK__ 1
+#define __UINTMAX_TYPE__ long long unsigned int
+#define __USER_LABEL_PREFIX__
+#define __VERSION__ "4.2.1 Compatible Clang 3.4 (https://bitbucket.org/loganchien/clang c34bb12af3af42f671296cdb978b34b931062d2a) (https://bitbucket.org/loganchien/llvm d09f2eff406d17c86d51db7660bd374cf092e6ed)"
+#define __VFP_FP__ 1
+#define __WCHAR_MAX__ 4294967295U
+#define __WCHAR_TYPE__ unsigned int
+#define __WCHAR_UNSIGNED__ 1
+#define __WCHAR_WIDTH__ 32
+#define __WINT_TYPE__ unsigned int
+#define __WINT_UNSIGNED__ 1
+#define __WINT_WIDTH__ 32
+#define __arm 1
+#define __arm__ 1
+#define __clang__ 1
+#define __clang_major__ 3
+#define __clang_minor__ 4
+#define __clang_patchlevel__ 0
+#define __clang_version__ "3.4 (https://bitbucket.org/loganchien/clang c34bb12af3af42f671296cdb978b34b931062d2a) (https://bitbucket.org/loganchien/llvm d09f2eff406d17c86d51db7660bd374cf092e6ed)"
+#define __cplusplus 201103L
+#define __cpp_attributes 200809
+#define __cpp_constexpr 200704
+#define __cpp_decltype 200707
+#define __cpp_lambdas 200907
+#define __cpp_raw_strings 200710
+#define __cpp_rvalue_references 200610
+#define __cpp_static_assert 200410
+#define __cpp_unicode_characters 200704
+#define __cpp_unicode_literals 200710
+#define __cpp_user_defined_literals 200809
+#define __cpp_variadic_templates 200704
+#define __gnu_linux__ 1
+#define __linux 1
+#define __linux__ 1
+#define __llvm__ 1
+#define __pic__ 1
+#define __private_extern__ extern
+#define __unix 1
+#define __unix__ 1
+#define ANDROID
+#endif
+
+// --- Include directories begin --- //
+//C:/Android/ndk/platforms/android-3/arch-arm/usr/include
+//C:/Users/eayusov/Documents/Sandbox/Common/Android/jni/../../include
+//C:\Android\ndk\toolchains\llvm-3.4\prebuilt\windows\bin\..\lib\clang\3.4\include
+// --- Library directories end --- //
+
+
+// --- Library directories begin --- //
+// --- Library directories begin --- //
+
diff --git a/Graphics/GraphicsEngineOpenGL/build/Windows/Android/gcc_Release.h b/Graphics/GraphicsEngineOpenGL/build/Windows/Android/gcc_Release.h
new file mode 100644
index 00000000..6ca2abab
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/build/Windows/Android/gcc_Release.h
@@ -0,0 +1,380 @@
+/*
+ This file is only used by IntelliSense (VisualStudio code suggestion system)
+ DO NOT INCLUDE THIS FILE FROM YOUR ACTUAL SOURCE FILES.
+ This file lists the preprocessor macros extracted from your GCC.
+ It is needed for IntelliSense to parse other header files correctly.
+*/
+#ifdef _MSC_VER
+#define __DBL_MIN_EXP__ (-1021)
+#define __HQ_FBIT__ 15
+#define __UINT_LEAST16_MAX__ 65535
+#define __ARM_SIZEOF_WCHAR_T 32
+#define __ATOMIC_ACQUIRE 2
+#define __SFRACT_IBIT__ 0
+#define __FLT_MIN__ 1.1754943508222875e-38F
+#define __UFRACT_MAX__ 0XFFFFP-16UR
+#define __UINT_LEAST8_TYPE__ unsigned char
+#define __DQ_FBIT__ 63
+#define __ARM_FEATURE_SAT 1
+#define __ULFRACT_FBIT__ 32
+#define __SACCUM_EPSILON__ 0x1P-7HK
+#define __CHAR_BIT__ 8
+#define __USQ_IBIT__ 0
+#define __UINT8_MAX__ 255
+#define __ACCUM_FBIT__ 15
+#define __ANDROID__ 1
+#define __WINT_MAX__ 4294967295U
+#define __USFRACT_FBIT__ 8
+#define __ORDER_LITTLE_ENDIAN__ 1234
+#define __SIZE_MAX__ 4294967295U
+#define __ARM_ARCH_ISA_ARM 1
+#define __WCHAR_MAX__ 4294967295U
+#define __LACCUM_IBIT__ 32
+#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
+#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
+#define __DBL_DENORM_MIN__ double(4.9406564584124654e-324L)
+#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
+#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
+#define __FLT_EVAL_METHOD__ 0
+#define __unix__ 1
+#define __LLACCUM_MAX__ 0X7FFFFFFFFFFFFFFFP-31LLK
+#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
+#define __FRACT_FBIT__ 15
+#define __UINT_FAST64_MAX__ 18446744073709551615ULL
+#define __SIG_ATOMIC_TYPE__ int
+#define __UACCUM_FBIT__ 16
+#define __DBL_MIN_10_EXP__ (-307)
+#define __FINITE_MATH_ONLY__ 0
+#define __ARMEL__ 1
+#define __ARM_FEATURE_UNALIGNED 1
+#define __LFRACT_IBIT__ 0
+#define __GNUC_PATCHLEVEL__ 0
+#define __LFRACT_MAX__ 0X7FFFFFFFP-31LR
+#define __UINT_FAST8_MAX__ 255
+#define __DEC64_MAX_EXP__ 385
+#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
+#define __SA_FBIT__ 15
+#define __SHRT_MAX__ 32767
+#define __LDBL_MAX__ 1.7976931348623157e+308L
+#define __FRACT_MAX__ 0X7FFFP-15R
+#define __UFRACT_FBIT__ 16
+#define __ARM_FP 12
+#define __UFRACT_MIN__ 0.0UR
+#define __UINT_LEAST8_MAX__ 255
+#define __GCC_ATOMIC_BOOL_LOCK_FREE 2
+#define __UINTMAX_TYPE__ long long unsigned int
+#define __LLFRACT_EPSILON__ 0x1P-63LLR
+#define __linux 1
+#define __DEC32_EPSILON__ 1E-6DF
+#define __CHAR_UNSIGNED__ 1
+#define __UINT32_MAX__ 4294967295U
+#define __GXX_EXPERIMENTAL_CXX0X__ 1
+#define __ULFRACT_MAX__ 0XFFFFFFFFP-32ULR
+#define __TA_IBIT__ 64
+#define __LDBL_MAX_EXP__ 1024
+#define __WINT_MIN__ 0U
+#define __linux__ 1
+#define __ULLFRACT_MIN__ 0.0ULLR
+#define __SCHAR_MAX__ 127
+#define __WCHAR_MIN__ 0U
+#define __DBL_DIG__ 15
+#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
+#define __LLACCUM_MIN__ (-0X1P31LLK-0X1P31LLK)
+#define __SIZEOF_INT__ 4
+#define __SIZEOF_POINTER__ 4
+#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
+#define __USACCUM_IBIT__ 8
+#define __USER_LABEL_PREFIX__
+#define __STDC_HOSTED__ 1
+#define __LDBL_HAS_INFINITY__ 1
+#define __LFRACT_MIN__ (-0.5LR-0.5LR)
+#define __HA_IBIT__ 8
+#define __ARM_NEON_FP 4
+#define __TQ_IBIT__ 0
+#define __FLT_EPSILON__ 1.1920928955078125e-7F
+#define __APCS_32__ 1
+#define __GXX_WEAK__ 1
+#define __USFRACT_IBIT__ 0
+#define __LDBL_MIN__ 2.2250738585072014e-308L
+#define __FRACT_MIN__ (-0.5R-0.5R)
+#define __DEC32_MAX__ 9.999999E96DF
+#define __DA_IBIT__ 32
+#define __ARM_SIZEOF_MINIMAL_ENUM 4
+#define __INT32_MAX__ 2147483647
+#define __UQQ_FBIT__ 8
+#define __SIZEOF_LONG__ 4
+#define __UACCUM_MAX__ 0XFFFFFFFFP-16UK
+#define __DECIMAL_DIG__ 17
+#define __LFRACT_EPSILON__ 0x1P-31LR
+#define __ULFRACT_MIN__ 0.0ULR
+#define __LDBL_HAS_QUIET_NAN__ 1
+#define __ULACCUM_IBIT__ 32
+#define __UACCUM_EPSILON__ 0x1P-16UK
+#define __GNUC__ 4
+#define __ULLACCUM_MAX__ 0XFFFFFFFFFFFFFFFFP-32ULLK
+#define __GXX_RTTI 1
+#define __HQ_IBIT__ 0
+#define __FLT_HAS_DENORM__ 1
+#define __SIZEOF_LONG_DOUBLE__ 8
+#define __BIGGEST_ALIGNMENT__ 8
+#define __GNUC_STDC_INLINE__ 1
+#define __DQ_IBIT__ 0
+#define __DBL_MAX__ double(1.7976931348623157e+308L)
+#define __ULFRACT_IBIT__ 0
+#define __INT_FAST32_MAX__ 2147483647
+#define __DBL_HAS_INFINITY__ 1
+#define __INT64_MAX__ 9223372036854775807LL
+#define __ACCUM_IBIT__ 16
+#define __DEC32_MIN_EXP__ (-94)
+#define __THUMB_INTERWORK__ 1
+#define __LACCUM_MAX__ 0X7FFFFFFFFFFFFFFFP-31LK
+#define __INT_FAST16_TYPE__ int
+#define __STRICT_ANSI__ 1
+#define __LDBL_HAS_DENORM__ 1
+#define __ARM_FEATURE_LDREX 15
+#define __cplusplus 201103L
+#define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+#define __INT_LEAST32_MAX__ 2147483647
+#define __ARM_PCS 1
+#define __DEC32_MIN__ 1E-95DF
+#define __ACCUM_MAX__ 0X7FFFFFFFP-15K
+#define __DEPRECATED 1
+#define __DBL_MAX_EXP__ 1024
+#define __USACCUM_EPSILON__ 0x1P-8UHK
+#define __DEC128_EPSILON__ 1E-33DL
+#define __SFRACT_MAX__ 0X7FP-7HR
+#define __FRACT_IBIT__ 0
+#define __PTRDIFF_MAX__ 2147483647
+#define __UACCUM_MIN__ 0.0UK
+#define __UACCUM_IBIT__ 16
+#define __GNUG__ 4
+#define __LONG_LONG_MAX__ 9223372036854775807LL
+#define __SIZEOF_SIZE_T__ 4
+#define __ULACCUM_MAX__ 0XFFFFFFFFFFFFFFFFP-32ULK
+#define __SIZEOF_WINT_T__ 4
+#define __SA_IBIT__ 16
+#define __ULLACCUM_MIN__ 0.0ULLK
+#define __GXX_ABI_VERSION 1002
+#define __UTA_FBIT__ 64
+#define __FLT_MIN_EXP__ (-125)
+#define __USFRACT_MAX__ 0XFFP-8UHR
+#define __UFRACT_IBIT__ 0
+#define __ARM_FEATURE_QBIT 1
+#define __INT_FAST64_TYPE__ long long int
+#define __DBL_MIN__ double(2.2250738585072014e-308L)
+#define __FLT_MIN_10_EXP__ (-37)
+#define __LACCUM_MIN__ (-0X1P31LK-0X1P31LK)
+#define __ULLACCUM_FBIT__ 32
+#define __GXX_TYPEINFO_EQUALITY_INLINE 0
+#define __ULLFRACT_EPSILON__ 0x1P-64ULLR
+#define __DEC128_MIN__ 1E-6143DL
+#define __REGISTER_PREFIX__
+#define __UINT16_MAX__ 65535
+#define __DBL_HAS_DENORM__ 1
+#define __ACCUM_MIN__ (-0X1P15K-0X1P15K)
+#define __SQ_IBIT__ 0
+#define __UINT8_TYPE__ unsigned char
+#define __UHA_FBIT__ 8
+#define __NO_INLINE__ 1
+#define __SFRACT_MIN__ (-0.5HR-0.5HR)
+#define __UTQ_FBIT__ 128
+#define __FLT_MANT_DIG__ 24
+#define __VERSION__ "4.8"
+#define __ULLFRACT_FBIT__ 64
+#define __FRACT_EPSILON__ 0x1P-15R
+#define __ULACCUM_MIN__ 0.0ULK
+#define __UDA_FBIT__ 32
+#define __LLACCUM_EPSILON__ 0x1P-31LLK
+#define __GCC_ATOMIC_INT_LOCK_FREE 2
+#define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
+#define __USFRACT_MIN__ 0.0UHR
+#define __ULLACCUM_IBIT__ 32
+#define __UQQ_IBIT__ 0
+#define __DEC64_EPSILON__ 1E-15DD
+#define __ORDER_PDP_ENDIAN__ 3412
+#define __DEC128_MIN_EXP__ (-6142)
+#define __UHQ_FBIT__ 16
+#define __LLACCUM_FBIT__ 31
+#define __INT_FAST32_TYPE__ int
+#define __UINT_LEAST16_TYPE__ short unsigned int
+#define __INT16_MAX__ 32767
+#define __SIZE_TYPE__ unsigned int
+#define __UINT64_MAX__ 18446744073709551615ULL
+#define __UDQ_FBIT__ 64
+#define __INT8_TYPE__ signed char
+#define __ELF__ 1
+#define __ULFRACT_EPSILON__ 0x1P-32ULR
+#define __LLFRACT_FBIT__ 63
+#define __FLT_RADIX__ 2
+#define __INT_LEAST16_TYPE__ short int
+#define __ARM_ARCH_PROFILE 65
+#define __LDBL_EPSILON__ 2.2204460492503131e-16L
+#define __SACCUM_MAX__ 0X7FFFP-7HK
+#define __SIG_ATOMIC_MAX__ 2147483647
+#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+#define __VFP_FP__ 1
+#define __SIZEOF_PTRDIFF_T__ 4
+#define __LACCUM_EPSILON__ 0x1P-31LK
+#define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
+#define __INT_FAST16_MAX__ 2147483647
+#define __UINT_FAST32_MAX__ 4294967295U
+#define __UINT_LEAST64_TYPE__ long long unsigned int
+#define __USACCUM_MAX__ 0XFFFFP-8UHK
+#define __SFRACT_EPSILON__ 0x1P-7HR
+#define __FLT_HAS_QUIET_NAN__ 1
+#define __FLT_MAX_10_EXP__ 38
+#define __LONG_MAX__ 2147483647L
+#define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
+#define __FLT_HAS_INFINITY__ 1
+#define __unix 1
+#define __USA_FBIT__ 16
+#define __UINT_FAST16_TYPE__ unsigned int
+#define __DEC64_MAX__ 9.999999999999999E384DD
+#define __CHAR16_TYPE__ short unsigned int
+#define __PRAGMA_REDEFINE_EXTNAME 1
+#define __INT_LEAST16_MAX__ 32767
+#define __DEC64_MANT_DIG__ 16
+#define __UINT_LEAST32_MAX__ 4294967295U
+#define __SACCUM_FBIT__ 7
+#define __GCC_ATOMIC_LONG_LOCK_FREE 2
+#define __INT_LEAST64_TYPE__ long long int
+#define __ARM_FEATURE_CLZ 1
+#define __INT16_TYPE__ short int
+#define __INT_LEAST8_TYPE__ signed char
+#define __SQ_FBIT__ 31
+#define __DEC32_MAX_EXP__ 97
+#define __ARM_ARCH_ISA_THUMB 2
+#define __INT_FAST8_MAX__ 127
+#define __ARM_ARCH 7
+#define __INTPTR_MAX__ 2147483647
+#define __QQ_FBIT__ 7
+#define __UTA_IBIT__ 64
+#define __EXCEPTIONS 1
+#define __LDBL_MANT_DIG__ 53
+#define __SFRACT_FBIT__ 7
+#define __SACCUM_MIN__ (-0X1P7HK-0X1P7HK)
+#define __DBL_HAS_QUIET_NAN__ 1
+#define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
+#define __INTPTR_TYPE__ int
+#define __UINT16_TYPE__ short unsigned int
+#define __WCHAR_TYPE__ unsigned int
+#define __SIZEOF_FLOAT__ 4
+#define __USQ_FBIT__ 32
+#define __pic__ 1
+#define __UINTPTR_MAX__ 4294967295U
+#define __DEC64_MIN_EXP__ (-382)
+#define __INT_FAST64_MAX__ 9223372036854775807LL
+#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+#define __FLT_DIG__ 6
+#define __UINT_FAST64_TYPE__ long long unsigned int
+#define __INT_MAX__ 2147483647
+#define __LACCUM_FBIT__ 31
+#define __USACCUM_MIN__ 0.0UHK
+#define __UHA_IBIT__ 8
+#define __INT64_TYPE__ long long int
+#define __FLT_MAX_EXP__ 128
+#define __UTQ_IBIT__ 0
+#define __DBL_MANT_DIG__ 53
+#define __INT_LEAST64_MAX__ 9223372036854775807LL
+#define __DEC64_MIN__ 1E-383DD
+#define __WINT_TYPE__ unsigned int
+#define __UINT_LEAST32_TYPE__ unsigned int
+#define __SIZEOF_SHORT__ 2
+#define __ULLFRACT_IBIT__ 0
+#define __LDBL_MIN_EXP__ (-1021)
+#define __arm__ 1
+#define __UDA_IBIT__ 32
+#define __INT_LEAST8_MAX__ 127
+#define __SSP__ 1
+#define __LFRACT_FBIT__ 31
+#define __WCHAR_UNSIGNED__ 1
+#define __ARM_ARCH_7A__ 1
+#define __LDBL_MAX_10_EXP__ 308
+#define __ATOMIC_RELAXED 0
+#define __DBL_EPSILON__ double(2.2204460492503131e-16L)
+#define __ARM_FEATURE_SIMD32 1
+#define __INT_LEAST32_TYPE__ int
+#define __SIZEOF_WCHAR_T__ 4
+#define __UINT64_TYPE__ long long unsigned int
+#define __LLFRACT_MAX__ 0X7FFFFFFFFFFFFFFFP-63LLR
+#define __TQ_FBIT__ 127
+#define __INT_FAST8_TYPE__ signed char
+#define __ULLACCUM_EPSILON__ 0x1P-32ULLK
+#define __UHQ_IBIT__ 0
+#define __LLACCUM_IBIT__ 32
+#define __DBL_DECIMAL_DIG__ 17
+#define __DEC_EVAL_METHOD__ 2
+#define __TA_FBIT__ 63
+#define __UDQ_IBIT__ 0
+#define __ORDER_BIG_ENDIAN__ 4321
+#define __ACCUM_EPSILON__ 0x1P-15K
+#define __INTMAX_MAX__ 9223372036854775807LL
+#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+#define __FLT_DENORM_MIN__ 1.4012984643248171e-45F
+#define __LLFRACT_IBIT__ 0
+#define __INT8_MAX__ 127
+#define __PIC__ 1
+#define __UINT_FAST32_TYPE__ unsigned int
+#define __CHAR32_TYPE__ unsigned int
+#define __FLT_MAX__ 3.4028234663852886e+38F
+#define __USACCUM_FBIT__ 8
+#define __INT32_TYPE__ int
+#define __SIZEOF_DOUBLE__ 8
+#define __UFRACT_EPSILON__ 0x1P-16UR
+#define __INTMAX_TYPE__ long long int
+#define __DEC128_MAX_EXP__ 6145
+#define __ATOMIC_CONSUME 1
+#define __GNUC_MINOR__ 8
+#define __UINTMAX_MAX__ 18446744073709551615ULL
+#define __DEC32_MANT_DIG__ 7
+#define __HA_FBIT__ 7
+#define __DBL_MAX_10_EXP__ 308
+#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
+#define __STDC__ 1
+#define __PTRDIFF_TYPE__ int
+#define __LLFRACT_MIN__ (-0.5LLR-0.5LLR)
+#define __ATOMIC_SEQ_CST 5
+#define __DA_FBIT__ 31
+#define __UINT32_TYPE__ unsigned int
+#define __UINTPTR_TYPE__ unsigned int
+#define __USA_IBIT__ 16
+#define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
+#define __ARM_EABI__ 1
+#define __DEC128_MANT_DIG__ 34
+#define __LDBL_MIN_10_EXP__ (-307)
+#define __SIZEOF_LONG_LONG__ 8
+#define __ULACCUM_EPSILON__ 0x1P-32ULK
+#define __SACCUM_IBIT__ 8
+#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
+#define __LDBL_DIG__ 15
+#define __FLT_DECIMAL_DIG__ 9
+#define __UINT_FAST16_MAX__ 4294967295U
+#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
+#define __ULLFRACT_MAX__ 0XFFFFFFFFFFFFFFFFP-64ULLR
+#define __UINT_FAST8_TYPE__ unsigned char
+#define _GNU_SOURCE 1
+#define __USFRACT_EPSILON__ 0x1P-8UHR
+#define __ULACCUM_FBIT__ 32
+#define __ARM_FEATURE_DSP 1
+#define __QQ_IBIT__ 0
+#define __ATOMIC_ACQ_REL 4
+#define __ATOMIC_RELEASE 3
+#define ANDROID
+#endif
+
+// --- Include directories begin --- //
+//C:/Android/ndk/platforms/android-3/arch-arm/usr/include
+//C:\Android\ndk\toolchains\arm-linux-androideabi-4.8\prebuilt\windows\bin\../lib/gcc/arm-linux-androideabi/4.8/include
+//C:\Android\ndk\toolchains\arm-linux-androideabi-4.8\prebuilt\windows\bin\../lib/gcc/arm-linux-androideabi/4.8/include-fixed
+// --- Library directories end --- //
+
+
+// --- Library directories begin --- //
+//C:/Android/ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.8/armv7-a/
+//C:/Android/ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/lib/armv7-a/
+//C:/Android/ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.8/
+//C:/Android/ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/windows/bin/../lib/gcc/
+//C:/Android/ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/lib/
+// --- Library directories begin --- //
+
diff --git a/Graphics/GraphicsEngineOpenGL/build/Windows/EngineRoot.props b/Graphics/GraphicsEngineOpenGL/build/Windows/EngineRoot.props
new file mode 100644
index 00000000..02287e9c
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/build/Windows/EngineRoot.props
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ImportGroup Label="PropertySheets" />
+ <PropertyGroup Label="UserMacros">
+ <EngineRoot>..\..\..\..</EngineRoot>
+ <GraphicsRoot>..\..\..</GraphicsRoot>
+ <ProjectRoot>..\..</ProjectRoot>
+ </PropertyGroup>
+ <PropertyGroup />
+ <ItemDefinitionGroup />
+ <ItemGroup>
+ <BuildMacro Include="EngineRoot">
+ <Value>$(EngineRoot)</Value>
+ </BuildMacro>
+ <BuildMacro Include="GraphicsRoot">
+ <Value>$(GraphicsRoot)</Value>
+ </BuildMacro>
+ <BuildMacro Include="ProjectRoot">
+ <Value>$(ProjectRoot)</Value>
+ </BuildMacro>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL-Debug.vgdbsettings b/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL-Debug.vgdbsettings
new file mode 100644
index 00000000..3f5b24b1
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL-Debug.vgdbsettings
@@ -0,0 +1,76 @@
+<?xml version="1.0"?>
+<VisualGDBProjectSettings2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <ConfigurationName>Debug</ConfigurationName>
+ <Project xsi:type="com.visualgdb.project.android">
+ <CustomSourceDirectories>
+ <Directories />
+ <PathStyle>MinGWWindowsSlash</PathStyle>
+ </CustomSourceDirectories>
+ <AndroidProjectPath>$(ProjectDir)</AndroidProjectPath>
+ </Project>
+ <Build xsi:type="com.visualgdb.build.android">
+ <AndroidPlatform>android-19</AndroidPlatform>
+ <IsDebugConfiguration>true</IsDebugConfiguration>
+ <JNIOnlyBuild>true</JNIOnlyBuild>
+ <AdditionalDirectoriesToDeleteOnClean>bin;obj</AdditionalDirectoriesToDeleteOnClean>
+ <DeleteANTFilesOnClean>false</DeleteANTFilesOnClean>
+ <DoNotEditAndroidManifest>false</DoNotEditAndroidManifest>
+ <CustomActions />
+ </Build>
+ <Debug xsi:type="com.visualgdb.debug.android">
+ <AdditionalStartupCommands />
+ <AdditionalGDBSettings>
+ <FilterSpuriousStoppedNotifications>false</FilterSpuriousStoppedNotifications>
+ <ForceSingleThreadedMode>false</ForceSingleThreadedMode>
+ <PendingBreakpointsSupported>true</PendingBreakpointsSupported>
+ <DisableChildRanges>false</DisableChildRanges>
+ <UseAppleExtensions>false</UseAppleExtensions>
+ <CanAcceptCommandsWhileRunning>false</CanAcceptCommandsWhileRunning>
+ <MakeLogFile>false</MakeLogFile>
+ <IgnoreModuleEventsWhileStepping>true</IgnoreModuleEventsWhileStepping>
+ <UseRelativePathsOnly>false</UseRelativePathsOnly>
+ <ExitAction>KillApp</ExitAction>
+ <Features>
+ <DisableAutoDetection>false</DisableAutoDetection>
+ <UseFrameParameter>false</UseFrameParameter>
+ <SimpleValuesFlagSupported>false</SimpleValuesFlagSupported>
+ <ListLocalsSupported>false</ListLocalsSupported>
+ <ByteLevelMemoryCommandsAvailable>false</ByteLevelMemoryCommandsAvailable>
+ <ThreadInfoSupported>false</ThreadInfoSupported>
+ <PendingBreakpointsSupported>false</PendingBreakpointsSupported>
+ <SupportTargetCommand>false</SupportTargetCommand>
+ </Features>
+ <DisableDisassembly>false</DisableDisassembly>
+ <ExamineMemoryWithXCommand>false</ExamineMemoryWithXCommand>
+ <StepIntoNewInstanceEntry>main</StepIntoNewInstanceEntry>
+ <ExamineRegistersInRawFormat>true</ExamineRegistersInRawFormat>
+ </AdditionalGDBSettings>
+ <LaunchGDBSettings xsi:type="GDBLaunchParametersAndroid" />
+ <GenerateCtrlBreakInsteadOfCtrlC>false</GenerateCtrlBreakInsteadOfCtrlC>
+ <UseDefaultInstallDir>false</UseDefaultInstallDir>
+ <RemotePort>5039</RemotePort>
+ <LocalPort>5039</LocalPort>
+ <GDBServerStartupTimeout>10000</GDBServerStartupTimeout>
+ <AdditionalGDBServerStartupDelay>0</AdditionalGDBServerStartupDelay>
+ <DoubleSlashWorkaround>false</DoubleSlashWorkaround>
+ <AlreadyRunningDecision>Ask</AlreadyRunningDecision>
+ <ShowLogCat>true</ShowLogCat>
+ <EnableThreadNameWatcher>true</EnableThreadNameWatcher>
+ </Debug>
+ <CustomBuild>
+ <PreBuildActions />
+ <PostBuildActions />
+ <PreCleanActions />
+ <PostCleanActions />
+ </CustomBuild>
+ <CustomDebug>
+ <PreDebugActions />
+ <PostDebugActions />
+ <BreakMode>Default</BreakMode>
+ </CustomDebug>
+ <CustomShortcuts>
+ <Shortcuts />
+ <ShowMessageAfterExecuting>true</ShowMessageAfterExecuting>
+ </CustomShortcuts>
+ <UserDefinedVariables />
+</VisualGDBProjectSettings2> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL-Release.vgdbsettings b/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL-Release.vgdbsettings
new file mode 100644
index 00000000..669691f2
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL-Release.vgdbsettings
@@ -0,0 +1,76 @@
+<?xml version="1.0"?>
+<VisualGDBProjectSettings2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <ConfigurationName>Release</ConfigurationName>
+ <Project xsi:type="com.visualgdb.project.android">
+ <CustomSourceDirectories>
+ <Directories />
+ <PathStyle>MinGWWindowsSlash</PathStyle>
+ </CustomSourceDirectories>
+ <AndroidProjectPath>$(ProjectDir)</AndroidProjectPath>
+ </Project>
+ <Build xsi:type="com.visualgdb.build.android">
+ <AndroidPlatform>android-19</AndroidPlatform>
+ <IsDebugConfiguration>false</IsDebugConfiguration>
+ <JNIOnlyBuild>true</JNIOnlyBuild>
+ <AdditionalDirectoriesToDeleteOnClean>bin;obj</AdditionalDirectoriesToDeleteOnClean>
+ <DeleteANTFilesOnClean>false</DeleteANTFilesOnClean>
+ <DoNotEditAndroidManifest>false</DoNotEditAndroidManifest>
+ <CustomActions />
+ </Build>
+ <Debug xsi:type="com.visualgdb.debug.android">
+ <AdditionalStartupCommands />
+ <AdditionalGDBSettings>
+ <FilterSpuriousStoppedNotifications>false</FilterSpuriousStoppedNotifications>
+ <ForceSingleThreadedMode>false</ForceSingleThreadedMode>
+ <PendingBreakpointsSupported>true</PendingBreakpointsSupported>
+ <DisableChildRanges>false</DisableChildRanges>
+ <UseAppleExtensions>false</UseAppleExtensions>
+ <CanAcceptCommandsWhileRunning>false</CanAcceptCommandsWhileRunning>
+ <MakeLogFile>false</MakeLogFile>
+ <IgnoreModuleEventsWhileStepping>true</IgnoreModuleEventsWhileStepping>
+ <UseRelativePathsOnly>false</UseRelativePathsOnly>
+ <ExitAction>KillApp</ExitAction>
+ <Features>
+ <DisableAutoDetection>false</DisableAutoDetection>
+ <UseFrameParameter>false</UseFrameParameter>
+ <SimpleValuesFlagSupported>false</SimpleValuesFlagSupported>
+ <ListLocalsSupported>false</ListLocalsSupported>
+ <ByteLevelMemoryCommandsAvailable>false</ByteLevelMemoryCommandsAvailable>
+ <ThreadInfoSupported>false</ThreadInfoSupported>
+ <PendingBreakpointsSupported>false</PendingBreakpointsSupported>
+ <SupportTargetCommand>false</SupportTargetCommand>
+ </Features>
+ <DisableDisassembly>false</DisableDisassembly>
+ <ExamineMemoryWithXCommand>false</ExamineMemoryWithXCommand>
+ <StepIntoNewInstanceEntry>main</StepIntoNewInstanceEntry>
+ <ExamineRegistersInRawFormat>true</ExamineRegistersInRawFormat>
+ </AdditionalGDBSettings>
+ <LaunchGDBSettings xsi:type="GDBLaunchParametersAndroid" />
+ <GenerateCtrlBreakInsteadOfCtrlC>false</GenerateCtrlBreakInsteadOfCtrlC>
+ <UseDefaultInstallDir>false</UseDefaultInstallDir>
+ <RemotePort>5039</RemotePort>
+ <LocalPort>5039</LocalPort>
+ <GDBServerStartupTimeout>10000</GDBServerStartupTimeout>
+ <AdditionalGDBServerStartupDelay>0</AdditionalGDBServerStartupDelay>
+ <DoubleSlashWorkaround>false</DoubleSlashWorkaround>
+ <AlreadyRunningDecision>Ask</AlreadyRunningDecision>
+ <ShowLogCat>true</ShowLogCat>
+ <EnableThreadNameWatcher>true</EnableThreadNameWatcher>
+ </Debug>
+ <CustomBuild>
+ <PreBuildActions />
+ <PostBuildActions />
+ <PreCleanActions />
+ <PostCleanActions />
+ </CustomBuild>
+ <CustomDebug>
+ <PreDebugActions />
+ <PostDebugActions />
+ <BreakMode>Default</BreakMode>
+ </CustomDebug>
+ <CustomShortcuts>
+ <Shortcuts />
+ <ShowMessageAfterExecuting>true</ShowMessageAfterExecuting>
+ </CustomShortcuts>
+ <UserDefinedVariables />
+</VisualGDBProjectSettings2> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL.props b/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL.props
new file mode 100644
index 00000000..783f8a0f
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL.props
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ImportGroup Label="PropertySheets" />
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <IncludePath>$(GraphicsRoot)\GraphicsEngineOpenGL\include;$(GraphicsRoot)\GraphicsEngineOpenGL\interface;$(GraphicsRoot)\GraphicsEngine\include;$(GraphicsRoot)\GraphicsEngine\interface;$(GraphicsRoot)\GraphicsTools\include;$(EngineRoot)\Common\include;$(EngineRoot)\Common\interface;$(EngineRoot)\External\glew-1.10.0\include\GL;$(EngineRoot)\Platforms\interface;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup />
+ <ItemGroup />
+</Project> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL.vcxproj b/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL.vcxproj
new file mode 100644
index 00000000..34fbeeba
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL.vcxproj
@@ -0,0 +1,538 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="DbgDLL|ARM">
+ <Configuration>DbgDLL</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DbgDLL|Win32">
+ <Configuration>DbgDLL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DbgDLL|x64">
+ <Configuration>DbgDLL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|ARM">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelDLL|ARM">
+ <Configuration>RelDLL</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelDLL|Win32">
+ <Configuration>RelDLL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelDLL|x64">
+ <Configuration>RelDLL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM">
+ <Configuration>Release</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{15E346D3-FDE6-4B29-88B7-FCA14DADA501}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>GraphicsEngineOpenGL</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <PlatformToolset>v120</PlatformToolset>
+ <ConfigurationType>Makefile</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|ARM'" Label="Configuration">
+ <PlatformToolset>v120</PlatformToolset>
+ <ConfigurationType>Makefile</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <PlatformToolset>v120</PlatformToolset>
+ <ConfigurationType>Makefile</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|ARM'" Label="Configuration">
+ <PlatformToolset>v120</PlatformToolset>
+ <ConfigurationType>Makefile</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win32d.props" />
+ <Import Project="EngineRoot.props" />
+ <Import Project="GraphicsEngineOpenGL.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win32d.props" />
+ <Import Project="EngineRoot.props" />
+ <Import Project="GraphicsEngineOpenGL.props" />
+ <Import Project="..\..\..\Shared\build\Windows\DLLCommon.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win64d.props" />
+ <Import Project="EngineRoot.props" />
+ <Import Project="GraphicsEngineOpenGL.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win64d.props" />
+ <Import Project="EngineRoot.props" />
+ <Import Project="GraphicsEngineOpenGL.props" />
+ <Import Project="..\..\..\Shared\build\Windows\DLLCommon.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win32r.props" />
+ <Import Project="EngineRoot.props" />
+ <Import Project="GraphicsEngineOpenGL.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win32r.props" />
+ <Import Project="EngineRoot.props" />
+ <Import Project="GraphicsEngineOpenGL.props" />
+ <Import Project="..\..\..\Shared\build\Windows\DLLCommon.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win64r.props" />
+ <Import Project="EngineRoot.props" />
+ <Import Project="GraphicsEngineOpenGL.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win64r.props" />
+ <Import Project="EngineRoot.props" />
+ <Import Project="GraphicsEngineOpenGL.props" />
+ <Import Project="..\..\..\Shared\build\Windows\DLLCommon.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <Import Project="..\..\..\..\Shared\build\Windows\Android32d.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|ARM'" Label="PropertySheets">
+ <Import Project="..\..\..\..\Shared\build\Windows\Android32d.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <Import Project="..\..\..\..\Shared\build\Windows\Android32r.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|ARM'" Label="PropertySheets">
+ <Import Project="..\..\..\..\Shared\build\Windows\Android32r.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|x64'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|x64'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <NMakeForcedIncludes>$(ProjectDir)\Android\gcc_Debug.h;$(NMakeForcedIncludes)</NMakeForcedIncludes>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|ARM'">
+ <NMakeForcedIncludes>$(ProjectDir)\Android\gcc_Debug.h;$(NMakeForcedIncludes)</NMakeForcedIncludes>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <NMakeForcedIncludes>$(ProjectDir)\Android\gcc_Release.h;$(NMakeForcedIncludes)</NMakeForcedIncludes>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|ARM'">
+ <NMakeForcedIncludes>$(ProjectDir)\Android\gcc_Release.h;$(NMakeForcedIncludes)</NMakeForcedIncludes>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ModuleDefinitionFile>..\..\src\GraphicsEngineOpenGL.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ <Lib>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ModuleDefinitionFile>..\..\src\GraphicsEngineOpenGL.def</ModuleDefinitionFile>
+ </Link>
+ <Lib>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ModuleDefinitionFile>..\..\src\GraphicsEngineOpenGL.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ <Lib>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ModuleDefinitionFile>..\..\src\GraphicsEngineOpenGL.def</ModuleDefinitionFile>
+ </Link>
+ <Lib>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\include\BlendStateGLImpl.h" />
+ <ClInclude Include="..\..\include\BufferGLImpl.h" />
+ <ClInclude Include="..\..\include\BufferViewGLImpl.h" />
+ <ClInclude Include="..\..\include\DeviceContextGLImpl.h" />
+ <ClInclude Include="..\..\include\DSStateGLImpl.h" />
+ <ClInclude Include="..\..\include\FBOCache.h" />
+ <ClInclude Include="..\..\include\GLContextAndroid.h" />
+ <ClInclude Include="..\..\include\GLContextState.h" />
+ <ClInclude Include="..\..\include\GLContextWindows.h" />
+ <ClInclude Include="..\..\include\GLObjectWrapper.h" />
+ <ClInclude Include="..\..\include\GLProgram.h" />
+ <CustomBuild Include="..\..\include\GLSLDefinitions.h">
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(EngineRoot)\Utilities\File2Include\File2String.exe %(FullPath) $(ProjectRoot)\include\%(Filename)_inc.h</Command>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectRoot)\include\%(Filename)_inc.h</Outputs>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(EngineRoot)\Utilities\File2Include\File2String.exe %(FullPath) $(ProjectRoot)\include\%(Filename)_inc.h</Command>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectRoot)\include\%(Filename)_inc.h</Outputs>
+ <Command Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'">$(EngineRoot)\Utilities\File2Include\File2String.exe %(FullPath) $(ProjectRoot)\include\%(Filename)_inc.h</Command>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'">$(ProjectRoot)\include\%(Filename)_inc.h</Outputs>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'">$(EngineRoot)\Utilities\File2Include\File2String.exe %(FullPath) $(ProjectRoot)\include\%(Filename)_inc.h</Command>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'">$(ProjectRoot)\include\%(Filename)_inc.h</Outputs>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(EngineRoot)\Utilities\File2Include\File2String.exe %(FullPath) $(ProjectRoot)\include\%(Filename)_inc.h</Command>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectRoot)\include\%(Filename)_inc.h</Outputs>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(EngineRoot)\Utilities\File2Include\File2String.exe %(FullPath) $(ProjectRoot)\include\%(Filename)_inc.h</Command>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectRoot)\include\%(Filename)_inc.h</Outputs>
+ <Command Condition="'$(Configuration)|$(Platform)'=='DbgDLL|x64'">$(EngineRoot)\Utilities\File2Include\File2String.exe %(FullPath) $(ProjectRoot)\include\%(Filename)_inc.h</Command>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='DbgDLL|x64'">$(ProjectRoot)\include\%(Filename)_inc.h</Outputs>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelDLL|x64'">$(EngineRoot)\Utilities\File2Include\File2String.exe %(FullPath) $(ProjectRoot)\include\%(Filename)_inc.h</Command>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelDLL|x64'">$(ProjectRoot)\include\%(Filename)_inc.h</Outputs>
+ </CustomBuild>
+ <ClInclude Include="..\..\include\GLStubs.h" />
+ <ClInclude Include="..\..\include\GLTypeConversions.h" />
+ <ClInclude Include="..\..\include\HLSL2GLSLConverter.h" />
+ <ClInclude Include="..\..\include\RasterizerStateGLImpl.h" />
+ <ClInclude Include="..\..\include\RenderDeviceGLImpl.h" />
+ <ClInclude Include="..\..\include\RenderDeviceGLESImpl.h" />
+ <ClInclude Include="..\..\include\AsyncWritableResource.h" />
+ <ClInclude Include="..\..\include\ProgramPipelineCache.h" />
+ <ClInclude Include="..\..\include\SamplerGLImpl.h" />
+ <ClInclude Include="..\..\include\SwapChainGLImpl.h" />
+ <ClInclude Include="..\..\include\TexRegionRender.h" />
+ <ClInclude Include="..\..\include\Texture1DArray_OGL.h" />
+ <ClInclude Include="..\..\include\Texture1D_OGL.h" />
+ <ClInclude Include="..\..\include\Texture2DArray_OGL.h" />
+ <ClInclude Include="..\..\include\Texture2D_OGL.h" />
+ <ClInclude Include="..\..\include\Texture3D_OGL.h" />
+ <ClInclude Include="..\..\include\TextureBaseGL.h" />
+ <ClInclude Include="..\..\include\TextureViewGLImpl.h" />
+ <ClInclude Include="..\..\include\VAOCache.h" />
+ <ClInclude Include="..\..\include\VertexDescGLImpl.h" />
+ <ClInclude Include="..\..\include\ShaderGLImpl.h" />
+ <ClInclude Include="..\..\include\pch.h" />
+ <ClInclude Include="..\..\interface\BlendStateGL.h" />
+ <ClInclude Include="..\..\interface\BufferGL.h" />
+ <ClInclude Include="..\..\interface\BufferViewGL.h" />
+ <ClInclude Include="..\..\interface\DepthStencilStateGL.h" />
+ <ClInclude Include="..\..\interface\DeviceContextGL.h" />
+ <ClInclude Include="..\..\interface\RasterizerStateGL.h" />
+ <ClInclude Include="..\..\interface\RenderDeviceFactoryOpenGL.h" />
+ <ClInclude Include="..\..\interface\RenderDeviceGL.h" />
+ <ClInclude Include="..\..\interface\RenderDeviceGLES.h" />
+ <ClInclude Include="..\..\interface\BaseInterfacesGL.h" />
+ <ClInclude Include="..\..\interface\SamplerGL.h" />
+ <ClInclude Include="..\..\interface\ShaderGL.h" />
+ <ClInclude Include="..\..\interface\SwapChainGL.h" />
+ <ClInclude Include="..\..\interface\TextureGL.h" />
+ <ClInclude Include="..\..\interface\TextureViewGL.h" />
+ <ClInclude Include="..\..\interface\VertexDescriptionGL.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\BlendStateGLImpl.cpp" />
+ <ClCompile Include="..\..\src\BufferGLImpl.cpp" />
+ <ClCompile Include="..\..\src\BufferViewGLImpl.cpp" />
+ <ClCompile Include="..\..\src\DeviceContextGLImpl.cpp" />
+ <ClCompile Include="..\..\src\DLLMain.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DbgDLL|ARM'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='RelDLL|ARM'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="..\..\src\DSStateGLImpl.cpp" />
+ <ClCompile Include="..\..\src\FBOCache.cpp" />
+ <ClCompile Include="..\..\src\GLContextAndroid.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DbgDLL|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='RelDLL|x64'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="..\..\src\GLContextState.cpp" />
+ <ClCompile Include="..\..\src\GLContextWindows.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DbgDLL|ARM'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='RelDLL|ARM'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="..\..\src\GLObjectWrapper.cpp" />
+ <ClCompile Include="..\..\src\GLProgram.cpp" />
+ <ClCompile Include="..\..\src\GLStubs.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DbgDLL|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='RelDLL|x64'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="..\..\src\GLTypeConversions.cpp" />
+ <ClCompile Include="..\..\src\HLSL2GLSLConverter.cpp" />
+ <ClCompile Include="..\..\src\RasterizerStateGLImpl.cpp" />
+ <ClCompile Include="..\..\src\RenderDeviceGLImpl.cpp" />
+ <ClCompile Include="..\..\src\RenderDeviceGLESImpl.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DbgDLL|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='RelDLL|x64'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="..\..\src\ProgramPipelineCache.cpp" />
+ <ClCompile Include="..\..\src\SamplerGLImpl.cpp" />
+ <ClCompile Include="..\..\src\SwapChainGLImpl.cpp" />
+ <ClCompile Include="..\..\src\TexRegionRender.cpp" />
+ <ClCompile Include="..\..\src\Texture1DArray_OGL.cpp" />
+ <ClCompile Include="..\..\src\Texture1D_OGL.cpp" />
+ <ClCompile Include="..\..\src\Texture2DArray_OGL.cpp" />
+ <ClCompile Include="..\..\src\Texture2D_OGL.cpp" />
+ <ClCompile Include="..\..\src\Texture3D_OGL.cpp" />
+ <ClCompile Include="..\..\src\TextureBaseGL.cpp" />
+ <ClCompile Include="..\..\src\TextureViewGLImpl.cpp" />
+ <ClCompile Include="..\..\src\VAOCache.cpp" />
+ <ClCompile Include="..\..\src\VertexDescGLImpl.cpp" />
+ <ClCompile Include="..\..\src\RenderDeviceFactoryOpenGL.cpp" />
+ <ClCompile Include="..\..\src\ShaderGLImpl.cpp" />
+ <ClCompile Include="..\..\src\pch.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='DbgDLL|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='RelDLL|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\src\GraphicsEngineOpenGL.def" />
+ <None Include="jni\Android.mk" />
+ <None Include="jni\Application.mk" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\..\Common\build\Windows\Common.vcxproj">
+ <Project>{7380f7e6-315f-4b4e-92eb-e6aeee865298}</Project>
+ <Private>false</Private>
+ <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+ <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+ <LinkLibraryDependencies>true</LinkLibraryDependencies>
+ <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\..\External\glew-1.10.0\build\Windows\glew_static.vcxproj">
+ <Project>{664e6f0d-6784-4760-9565-d54f8eb1edf4}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\..\Platforms\Basic\build\Windows\BasicPlatform.vcxproj">
+ <Project>{8ada5f93-7a38-4ad8-b8f5-1ffd4d4f630c}</Project>
+ <Private>false</Private>
+ <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+ <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+ <LinkLibraryDependencies>true</LinkLibraryDependencies>
+ <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\..\Platforms\Windows\build\Windows\WindowsPlatform.vcxproj">
+ <Project>{58f32677-436b-412a-bbf8-2b1310d82cd8}</Project>
+ <Private>false</Private>
+ <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+ <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+ <LinkLibraryDependencies>true</LinkLibraryDependencies>
+ <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\GraphicsEngine\build\Windows\GraphicsEngine.vcxproj">
+ <Project>{052dd700-477c-4512-a7f4-b05ebef5c80e}</Project>
+ <Private>false</Private>
+ <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+ <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+ <LinkLibraryDependencies>true</LinkLibraryDependencies>
+ <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\GraphicsTools\build\Windows\GraphicsTools.vcxproj">
+ <Project>{c6014499-0cf2-43ec-a773-a4e354fb2d74}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL.vcxproj.filters b/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL.vcxproj.filters
new file mode 100644
index 00000000..03c80428
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/build/Windows/GraphicsEngineOpenGL.vcxproj.filters
@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="jni">
+ <UniqueIdentifier>{658fdc9e-6df5-44d2-9888-cdce02006b44}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Windows">
+ <UniqueIdentifier>{f078efc4-26ba-4803-a3a1-eb22a55e7ada}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Android">
+ <UniqueIdentifier>{10a6ba1a-4ccb-4242-969f-beb04bfd2b65}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Windows">
+ <UniqueIdentifier>{ff063a45-e896-4855-8d8d-508a663c5515}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Android">
+ <UniqueIdentifier>{564419f6-6302-4533-a5d3-c7e25a40a8af}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Interface">
+ <UniqueIdentifier>{f367269b-3ff3-4ab3-917a-e5a7779acefe}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Interface\Windows">
+ <UniqueIdentifier>{41dbc56a-4158-4750-bea6-7f28afeb1855}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Interface\Android">
+ <UniqueIdentifier>{365f79b5-3f7f-4f71-8b03-d34102794f1d}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\include\VAOCache.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\GLObjectWrapper.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\ProgramPipelineCache.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\GLTypeConversions.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\Texture1D_OGL.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\Texture1DArray_OGL.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\Texture2D_OGL.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\Texture2DArray_OGL.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\Texture3D_OGL.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\GLContextAndroid.h">
+ <Filter>Header Files\Android</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\GLProgram.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\GLContextState.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\AsyncWritableResource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\GLStubs.h">
+ <Filter>Header Files\Android</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\BufferGLImpl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\BufferViewGLImpl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\DSStateGLImpl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\SamplerGLImpl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\ShaderGLImpl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\TextureBaseGL.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\VertexDescGLImpl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\RenderDeviceGLImpl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\RenderDeviceGLESImpl.h">
+ <Filter>Header Files\Android</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\RenderDeviceGLES.h">
+ <Filter>Interface\Android</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\RenderDeviceGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\BufferGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\BaseInterfacesGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\BufferViewGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\DepthStencilStateGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\SamplerGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\ShaderGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\TextureGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\TextureViewGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\TextureViewGLImpl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\VertexDescriptionGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\DeviceContextGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\DeviceContextGLImpl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\RasterizerStateGLImpl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\RasterizerStateGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\BlendStateGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\BlendStateGLImpl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\FBOCache.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\SwapChainGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\SwapChainGLImpl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\GLContextWindows.h">
+ <Filter>Header Files\Windows</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\interface\RenderDeviceFactoryOpenGL.h">
+ <Filter>Interface</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\pch.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\HLSL2GLSLConverter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\TexRegionRender.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\VAOCache.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\GLObjectWrapper.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\ProgramPipelineCache.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\GLTypeConversions.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\Texture1D_OGL.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\Texture1DArray_OGL.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\Texture2D_OGL.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\Texture2DArray_OGL.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\Texture3D_OGL.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\GLContextWindows.cpp">
+ <Filter>Source Files\Windows</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\GLContextAndroid.cpp">
+ <Filter>Source Files\Android</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\GLProgram.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\GLContextState.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\GLStubs.cpp">
+ <Filter>Source Files\Android</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\BufferGLImpl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\BufferViewGLImpl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\DSStateGLImpl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\SamplerGLImpl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\ShaderGLImpl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\TextureBaseGL.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\VertexDescGLImpl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\RenderDeviceGLImpl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\TextureViewGLImpl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\RenderDeviceGLESImpl.cpp">
+ <Filter>Source Files\Android</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\DeviceContextGLImpl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\RasterizerStateGLImpl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\BlendStateGLImpl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\FBOCache.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\SwapChainGLImpl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\RenderDeviceFactoryOpenGL.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\pch.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\DLLMain.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\HLSL2GLSLConverter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\TexRegionRender.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="jni\Application.mk">
+ <Filter>jni</Filter>
+ </None>
+ <None Include="jni\Android.mk">
+ <Filter>jni</Filter>
+ </None>
+ <None Include="..\..\src\GraphicsEngineOpenGL.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="..\..\include\GLSLDefinitions.h">
+ <Filter>Header Files</Filter>
+ </CustomBuild>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineOpenGL/build/Windows/jni/Android.mk b/Graphics/GraphicsEngineOpenGL/build/Windows/jni/Android.mk
new file mode 100644
index 00000000..521821b3
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/build/Windows/jni/Android.mk
@@ -0,0 +1,68 @@
+# Android NDK project makefile autogenerated by Premake
+
+# Preamble
+DEPENDENCY_PATH := $(call my-dir)
+LOCAL_PATH := $(abspath $(DEPENDENCY_PATH))
+include $(CLEAR_VARS)
+
+
+# Project configuration
+LOCAL_MODULE := GraphicsEngineOpenGL
+LOCAL_CFLAGS := -std=c++11 -DUSE_GL3_STUB=1 -DENGINE_DLL -DBUILDING_DLL -fvisibility=hidden
+LOCAL_CPP_FEATURES := exceptions rtti
+LOCAL_STATIC_LIBRARIES += GraphicsEngine-prebuilt AndroidPlatform-prebuilt BasicPlatform-prebuilt GraphicsTools-prebuilt Common-prebuilt ndk_helper native_app_glue
+
+# Include paths
+PROJECT_ROOT := $(LOCAL_PATH)/../../..
+SOLUTION_ROOT := $(PROJECT_ROOT)/../..
+LOCAL_C_INCLUDES := $(PROJECT_ROOT)/include $(PROJECT_ROOT)/interface $(SOLUTION_ROOT)/External
+
+# Source files
+#VisualGDBAndroid: AutoUpdateSourcesInNextLine
+LOCAL_SRC_FILES := ../../../src/BlendStateGLImpl.cpp ../../../src/BufferGLImpl.cpp ../../../src/BufferViewGLImpl.cpp ../../../src/DeviceContextGLImpl.cpp ../../../src/DLLMain.cpp ../../../src/DSStateGLImpl.cpp ../../../src/FBOCache.cpp ../../../src/GLContextAndroid.cpp ../../../src/GLContextState.cpp ../../../src/GLContextWindows.cpp ../../../src/GLObjectWrapper.cpp ../../../src/GLProgram.cpp ../../../src/GLStubs.cpp ../../../src/GLTypeConversions.cpp ../../../src/HLSL2GLSLConverter.cpp ../../../src/RasterizerStateGLImpl.cpp ../../../src/RenderDeviceGLImpl.cpp ../../../src/RenderDeviceGLESImpl.cpp ../../../src/ProgramPipelineCache.cpp ../../../src/SamplerGLImpl.cpp ../../../src/SwapChainGLImpl.cpp ../../../src/TexRegionRender.cpp ../../../src/Texture1DArray_OGL.cpp ../../../src/Texture1D_OGL.cpp ../../../src/Texture2DArray_OGL.cpp ../../../src/Texture2D_OGL.cpp ../../../src/Texture3D_OGL.cpp ../../../src/TextureBaseGL.cpp ../../../src/TextureViewGLImpl.cpp ../../../src/VAOCache.cpp ../../../src/VertexDescGLImpl.cpp ../../../src/RenderDeviceFactoryOpenGL.cpp ../../../src/ShaderGLImpl.cpp ../../../src/pch.cpp
+
+#VisualGDBAndroid: VSExcludeListLocation
+VISUALGDB_VS_EXCLUDED_FILES_Release := ../../../src/DLLMain.cpp ../../../src/GLContextWindows.cpp
+VISUALGDB_VS_EXCLUDED_FILES_Debug := ../../../src/DLLMain.cpp ../../../src/GLContextWindows.cpp
+LOCAL_SRC_FILES := $(filter-out $(VISUALGDB_VS_EXCLUDED_FILES_$(VGDB_VSCONFIG)),$(LOCAL_SRC_FILES))
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+# Declare pre-built Common library
+LOCAL_MODULE := Common-prebuilt
+LOCAL_EXPORT_C_INCLUDES := $(SOLUTION_ROOT)/Common/include $(SOLUTION_ROOT)/Common/interface
+LOCAL_SRC_FILES := $(SOLUTION_ROOT)/Common/build/Windows/obj/local/$(TARGET_ARCH_ABI)/libCommon.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+
+include $(CLEAR_VARS)
+# Declare pre-built AndroidPlatform library
+LOCAL_MODULE := AndroidPlatform-prebuilt
+LOCAL_SRC_FILES := $(SOLUTION_ROOT)/Platforms/Android/build/Windows/obj/local/$(TARGET_ARCH_ABI)/libAndroidPlatform.a
+LOCAL_EXPORT_C_INCLUDES := $(SOLUTION_ROOT)/Platforms/interface
+include $(PREBUILT_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+# Declare pre-built BasicPlatform library
+LOCAL_MODULE := BasicPlatform-prebuilt
+LOCAL_SRC_FILES := $(SOLUTION_ROOT)/Platforms/Basic/build/Windows/obj/local/$(TARGET_ARCH_ABI)/libBasicPlatform.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+
+include $(CLEAR_VARS)
+# Declare pre-built GraphicsEngine library
+LOCAL_MODULE := GraphicsEngine-prebuilt
+LOCAL_SRC_FILES := $(SOLUTION_ROOT)/Graphics/GraphicsEngine/build/Windows/obj/local/$(TARGET_ARCH_ABI)/libGraphicsEngine.a
+LOCAL_EXPORT_C_INCLUDES := $(SOLUTION_ROOT)/Graphics/GraphicsEngine/include $(SOLUTION_ROOT)/Graphics/GraphicsEngine/interface
+include $(PREBUILT_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+# Declare pre-built Graphics Tools library
+LOCAL_MODULE := GraphicsTools-prebuilt
+LOCAL_SRC_FILES := $(SOLUTION_ROOT)/Graphics/GraphicsTools/build/Windows/obj/local/$(TARGET_ARCH_ABI)/libGraphicsTools.a
+LOCAL_EXPORT_C_INCLUDES := $(SOLUTION_ROOT)/Graphics/GraphicsTools/include
+include $(PREBUILT_STATIC_LIBRARY)
+
+$(call import-module,android/ndk_helper)
+$(call import-module,android/native_app_glue)
diff --git a/Graphics/GraphicsEngineOpenGL/build/Windows/jni/Application.mk b/Graphics/GraphicsEngineOpenGL/build/Windows/jni/Application.mk
new file mode 100644
index 00000000..c7e241e8
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/build/Windows/jni/Application.mk
@@ -0,0 +1,7 @@
+# Generated by VisualGDB
+
+DEPENDENCY_PATH := $(call my-dir)
+LOCAL_PATH := $(abspath $(DEPENDENCY_PATH))
+include $(LOCAL_PATH)/../../../../../Common/make/AppCommon.mk
+
+APP_MODULES := GraphicsEngineOpenGL \ No newline at end of file
diff --git a/Graphics/GraphicsEngineOpenGL/include/AsyncWritableResource.h b/Graphics/GraphicsEngineOpenGL/include/AsyncWritableResource.h
new file mode 100644
index 00000000..89547eb8
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/AsyncWritableResource.h
@@ -0,0 +1,65 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+namespace Diligent
+{
+
+class AsyncWritableResource
+{
+public:
+ AsyncWritableResource() : m_PendingMemoryBarriers( 0 ) {}
+
+ void SetPendingMemoryBarriers( Uint32 Barriers ){ m_PendingMemoryBarriers |= Barriers; }
+ Uint32 GetPendingMemortBarriers(){ return m_PendingMemoryBarriers;}
+
+private:
+ friend class GLContextState;
+ void ResetPendingMemoryBarriers( Uint32 Barriers ){ m_PendingMemoryBarriers = Barriers; }
+ void ClearPendingMemoryBarriers( Uint32 Barriers ){ m_PendingMemoryBarriers &= ~Barriers; }
+
+ // Buffer barriers:
+ // GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT
+ // GL_ELEMENT_ARRAY_BARRIER_BIT
+ // GL_UNIFORM_BARRIER_BIT
+ // GL_BUFFER_UPDATE_BARRIER_BIT
+ // GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT
+ // GL_SHADER_STORAGE_BARRIER_BIT
+
+ // Texture barriers:
+ // GL_TEXTURE_FETCH_BARRIER_BIT
+ // GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
+ // GL_PIXEL_BUFFER_BARRIER_BIT
+ // GL_TEXTURE_UPDATE_BARRIER_BIT
+
+ // Misc barriers:
+ // GL_FRAMEBUFFER_BARRIER_BIT
+ // GL_TRANSFORM_FEEDBACK_BARRIER_BIT
+ // GL_ATOMIC_COUNTER_BARRIER_BIT
+ // GL_QUERY_BUFFER_BARRIER_BIT
+
+ Uint32 m_PendingMemoryBarriers;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/BlendStateGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/BlendStateGLImpl.h
new file mode 100644
index 00000000..62874e60
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/BlendStateGLImpl.h
@@ -0,0 +1,47 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "BaseInterfacesGL.h"
+#include "BlendStateGL.h"
+#include "BlendStateBase.h"
+#include "RenderDevice.h"
+
+namespace Diligent
+{
+
+/// Implementation of the Diligent::IBlendStateGL interface
+class BlendStateGLImpl : public BlendStateBase<IBlendStateGL, IGLDeviceBaseInterface>
+{
+public:
+ typedef BlendStateBase<IBlendStateGL, IGLDeviceBaseInterface> TBlendStateBase;
+
+ BlendStateGLImpl(class IRenderDevice *pDeviceGL, const BlendStateDesc& BlendStateDesc, bool bIsDeviceInternal = false);
+ ~BlendStateGLImpl();
+
+ /// Queries the specific interface, see IObject::QueryInterface() for details
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface );
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h
new file mode 100644
index 00000000..342dec4d
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h
@@ -0,0 +1,69 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "BufferGL.h"
+#include "BufferBase.h"
+#include "GLObjectWrapper.h"
+#include "AsyncWritableResource.h"
+#include "BaseInterfacesGL.h"
+#include "BufferViewGLImpl.h"
+
+namespace Diligent
+{
+
+/// Implementation of the Diligent::IBufferGL interface
+class BufferGLImpl : public BufferBase<IBufferGL, BufferViewGLImpl>, public AsyncWritableResource
+{
+public:
+ typedef BufferBase<IBufferGL, BufferViewGLImpl> TBufferBase;
+
+ BufferGLImpl(class RenderDeviceGLImpl *pDeviceGL, const BufferDesc& BuffDesc, const BufferData &BuffData = BufferData(), bool IsDeviceInternal = false);
+ ~BufferGLImpl();
+
+ /// Queries the specific interface, see IObject::QueryInterface() for details
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ virtual void UpdateData(IDeviceContext *pContext, Uint32 Offset, Uint32 Size, const PVoid pData)override;
+ virtual void CopyData( IDeviceContext *pContext, IBuffer *pSrcBuffer, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size )override;
+ virtual void Map( IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapFlags, PVoid &pMappedData )override;
+ virtual void Unmap( IDeviceContext *pContext )override;
+
+ void BufferMemoryBarrier( Uint32 RequiredBarriers, class GLContextState &GLContextState );
+
+ const GLObjectWrappers::GLBufferObj& GetGLBufferHandle(){ return m_GlBuffer; }
+
+private:
+ virtual void CreateViewInternal( const struct BufferViewDesc &ViewDesc, class IBufferView **ppView, bool bIsDefaultView )override;
+
+ friend class DeviceContextGLImpl;
+ friend class VAOCache;
+
+ GLObjectWrappers::GLBufferObj m_GlBuffer;
+ Uint32 m_uiMapTarget;
+ GLenum m_GLUsageHint;
+ Bool m_bUseMapWriteDiscardBugWA;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/BufferViewGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/BufferViewGLImpl.h
new file mode 100644
index 00000000..2f7ed835
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/BufferViewGLImpl.h
@@ -0,0 +1,56 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "BufferViewGL.h"
+#include "BaseInterfacesGL.h"
+#include "BufferViewBase.h"
+#include "RenderDevice.h"
+#include "GLObjectWrapper.h"
+
+namespace Diligent
+{
+
+/// Implementation of the Diligent::IBufferViewGL interface
+class BufferViewGLImpl : public BufferViewBase<IBufferViewGL>
+{
+public:
+ typedef BufferViewBase<IBufferViewGL> TBuffViewBase;
+
+ BufferViewGLImpl( class IRenderDevice *pDevice,
+ class IDeviceContext *pContext,
+ const struct BufferViewDesc& ViewDesc,
+ class BufferGLImpl *pBuffer,
+ bool bIsDefaultView);
+
+ /// Queries the specific interface, see IObject::QueryInterface() for details
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface );
+
+ const GLObjectWrappers::GLTextureObj& GetTexBufferHandle(){ return m_GLTexBuffer; }
+
+private:
+ GLObjectWrappers::GLTextureObj m_GLTexBuffer;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/DSStateGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/DSStateGLImpl.h
new file mode 100644
index 00000000..38f8eaff
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/DSStateGLImpl.h
@@ -0,0 +1,46 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "BaseInterfacesGL.h"
+#include "DepthStencilStateGL.h"
+#include "DepthStencilStateBase.h"
+#include "RenderDevice.h"
+
+namespace Diligent
+{
+
+/// Implementation of the Diligent::IDepthStencilStateGL interface
+class DSStateGLImpl : public DepthStencilStateBase<IDepthStencilStateGL, IGLDeviceBaseInterface>
+{
+public:
+ typedef DepthStencilStateBase<IDepthStencilStateGL, IGLDeviceBaseInterface> TDSStateBase;
+
+ DSStateGLImpl(class IRenderDevice *pDeviceGL, const DepthStencilStateDesc& DepthStencilStateDesc, bool bIsDeviceInternal = false);
+ ~DSStateGLImpl();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface );
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h
new file mode 100644
index 00000000..08694a9f
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h
@@ -0,0 +1,97 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "DeviceContextGL.h"
+#include "DeviceContextBase.h"
+#include "BaseInterfacesGL.h"
+#include "GLContextState.h"
+
+namespace Diligent
+{
+
+/// Implementation of the Diligent::IDeviceContextGL interface
+class DeviceContextGLImpl : public DeviceContextBase<IDeviceContextGL>
+{
+public:
+ typedef DeviceContextBase<IDeviceContextGL> TDeviceContextBase;
+
+ DeviceContextGLImpl( class RenderDeviceGLImpl *pDeviceGL );
+
+ /// Queries the specific interface, see IObject::QueryInterface() for details.
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ virtual void SetShaders( IShader **ppShaders, Uint32 NumShadersToSet )override;
+
+ virtual void BindShaderResources( IResourceMapping *pResourceMapping, Uint32 Flags )override;
+
+ virtual void SetVertexBuffers( Uint32 StartSlot, Uint32 NumBuffersSet, IBuffer **ppBuffers, Uint32 *pStrides, Uint32 *pOffsets, Uint32 Flags )override;
+ virtual void ClearState()override;
+
+ virtual void SetVertexDescription( IVertexDescription *pVertexDesc )override;
+
+ virtual void SetIndexBuffer( IBuffer *pIndexBuffer, Uint32 ByteOffset )override;
+
+ virtual void SetDepthStencilState( IDepthStencilState *pDepthStencilState, Uint32 StencilRef = 0 )override;
+
+ virtual void SetRasterizerState( IRasterizerState *pRS )override;
+
+ virtual void SetBlendState( IBlendState *pBS, const float* pBlendFactors, Uint32 SampleMask )override;
+
+ virtual void SetViewports( Uint32 NumViewports, const Viewport *pViewports, Uint32 RTWidth, Uint32 RTHeight )override;
+
+ virtual void SetScissorRects( Uint32 NumRects, const Rect *pRects, Uint32 RTWidth, Uint32 RTHeight )override;
+
+ virtual void SetRenderTargets( Uint32 NumRenderTargets, ITextureView *ppRenderTargets[], ITextureView *pDepthStencil )override;
+
+ virtual void Draw( DrawAttribs &DrawAttribs )override;
+
+ virtual void DispatchCompute( const DispatchComputeAttribs &DispatchAttrs )override;
+
+ virtual void ClearDepthStencil( ITextureView *pView, Uint32 ClearFlags, float fDepth, Uint8 Stencil)override;
+
+ virtual void ClearRenderTarget( ITextureView *pView, const float *RGBA )override;
+
+ virtual void Flush()override;
+
+ void BindProgramResources( Uint32 &NewMemoryBarriers );
+
+ GLContextState &GetContextState(){return m_ContextState;}
+
+ void RebindRenderTargets();
+
+protected:
+ friend class BufferGLImpl;
+ friend class TextureBaseGL;
+ friend class VertexDescGLImpl;
+ friend class ShaderGLImpl;
+
+ GLContextState m_ContextState;
+
+private:
+ std::vector<class TextureBaseGL*> m_BoundWritableTextures;
+ std::vector<class BufferGLImpl*> m_BoundWritableBuffers;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/FBOCache.h b/Graphics/GraphicsEngineOpenGL/include/FBOCache.h
new file mode 100644
index 00000000..c1e601d8
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/FBOCache.h
@@ -0,0 +1,92 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "GraphicsTypes.h"
+#include "TextureView.h"
+#include "LockHelper.h"
+#include "HashUtils.h"
+#include "GLObjectWrapper.h"
+
+namespace Diligent
+{
+
+class FBOCache
+{
+public:
+ FBOCache();
+ ~FBOCache();
+
+ const GLObjectWrappers::GLFrameBufferObj& GetFBO( Uint32 NumRenderTargets,
+ ITextureView *ppRenderTargets[],
+ ITextureView *pDepthStencil,
+ class GLContextState &ContextState);
+ void OnReleaseTexture(ITexture *pTexture);
+
+private:
+ // This structure is used as the key to find FBO
+ struct FBOCacheKey
+ {
+ // Using pointers is not reliable!
+
+ Uint32 NumRenderTargets;
+
+ // Unique IDs of textures bound as render targets
+ Diligent::UniqueIdentifier RTIds[MaxRenderTargets];
+ TextureViewDesc RTVDescs[MaxRenderTargets];
+
+ // Unique IDs of texture bound as depth stencil
+ Diligent::UniqueIdentifier DSId;
+ TextureViewDesc DSVDesc;
+
+ mutable size_t Hash;
+
+ bool operator == (const FBOCacheKey &Key)const;
+
+ FBOCacheKey() :
+ NumRenderTargets( 0 ),
+ DSId(0),
+ Hash(0)
+ {
+ for( int rt = 0; rt < MaxRenderTargets; ++rt )
+ RTIds[rt] = 0;
+ }
+ };
+
+ struct FBOCacheKeyHashFunc
+ {
+ std::size_t operator() ( const FBOCacheKey& Key )const;
+ };
+
+
+ friend class RenderDeviceGLImpl;
+ ThreadingTools::LockFlag m_CacheLockFlag;
+ std::unordered_map<FBOCacheKey, GLObjectWrappers::GLFrameBufferObj, FBOCacheKeyHashFunc> m_Cache;
+
+ // Multimap that sets up correspondence between unique texture id and all
+ // FBOs it is used in
+ std::unordered_multimap<Diligent::UniqueIdentifier, FBOCacheKey> m_TexIdToKey;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLContextAndroid.h b/Graphics/GraphicsEngineOpenGL/include/GLContextAndroid.h
new file mode 100644
index 00000000..63299daf
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/GLContextAndroid.h
@@ -0,0 +1,83 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include <EGL/egl.h>
+#include <android\native_window.h>
+
+namespace Diligent
+{
+ struct ContextInitInfo
+ {
+ SwapChainDesc SwapChainAttribs;
+ void *pNativeWndHandle;
+ };
+
+ class GLContext
+ {
+ public:
+ GLContext( const ContextInitInfo &Info, DeviceCaps &DeviceCaps );
+ ~GLContext();
+
+ bool Init( ANativeWindow* window );
+
+ void SwapBuffers();
+
+ bool Invalidate();
+
+ void Suspend();
+ EGLint Resume( ANativeWindow* window );
+
+ const SwapChainDesc& GetSwapChainDesc(){ return SwapChainAttribs_; }
+
+ private:
+ //EGL configurations
+ ANativeWindow* window_;
+ EGLDisplay display_;
+ EGLSurface surface_;
+ EGLContext context_;
+ EGLConfig config_;
+
+ //Screen parameters
+ int32_t color_size_;
+ int32_t depth_size_;
+ int32_t major_version_;
+ int32_t minor_version_;
+
+ //Flags
+ bool gles_initialized_;
+ bool egl_context_initialized_;
+ bool es3_supported_;
+ float gl_version_;
+ bool context_valid_;
+
+ SwapChainDesc SwapChainAttribs_;
+
+ void InitGLES();
+ void Terminate();
+ bool InitEGLSurface();
+ bool InitEGLContext();
+ void FillDeviceCaps( DeviceCaps &DeviceCaps );
+ };
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLContextState.h b/Graphics/GraphicsEngineOpenGL/include/GLContextState.h
new file mode 100644
index 00000000..cda952e1
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/GLContextState.h
@@ -0,0 +1,212 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "GraphicsTypes.h"
+#include "GLObjectWrapper.h"
+#include "UniqueIdentifier.h"
+
+namespace Diligent
+{
+
+class GLContextState
+{
+public:
+ GLContextState(class RenderDeviceGLImpl *pDeviceGL);
+
+ void SetProgram( const GLObjectWrappers::GLProgramObj &GLProgram );
+ void SetPipeline( const GLObjectWrappers::GLPipelineObj &GLPipeline );
+ void BindVAO( const GLObjectWrappers::GLVertexArrayObj &VAO );
+ void BindFBO( const GLObjectWrappers::GLFrameBufferObj &FBO );
+ void SetActiveTexture( Int32 Index );
+ void BindTexture( Int32 Index, GLenum BindTarget, const GLObjectWrappers::GLTextureObj &Tex);
+ void BindSampler( Uint32 Index, const GLObjectWrappers::GLSamplerObj &GLSampler);
+ void BindImage( Uint32 Index, class TextureViewGLImpl *pTexView, GLint MipLevel, GLboolean IsLayered, GLint Layer, GLenum Access, GLenum Format );
+ void EnsureMemoryBarrier(Uint32 RequiredBarriers, class AsyncWritableResource *pRes = nullptr);
+ void SetPendingMemoryBarriers( Uint32 PendingBarriers );
+
+ void EnableDepthTest( Bool bEnable );
+ void EnableDepthWrites( Bool bEnable );
+ void SetDepthFunc(COMPARISON_FUNCTION CmpFunc);
+ void EnableStencilTest( Bool bEnable );
+ void SetStencilWriteMask( Uint8 StencilWriteMask );
+ void SetStencilFunc( GLenum Face, COMPARISON_FUNCTION Func, Int32 Ref, Uint32 Mask );
+ void SetStencilOp( GLenum Face, STENCIL_OP StencilFailOp, STENCIL_OP StencilDepthFailOp, STENCIL_OP StencilPassOp );
+
+ void SetFillMode( FILL_MODE FillMode );
+ void SetCullMode( CULL_MODE CullMode );
+ void SetFrontFace( Bool FrontCounterClockwise );
+ void SetDepthBias( float DepthBias, float fSlopeScaledDepthBias );
+ void SetDepthClamp( Bool bEnableDepthClamp );
+ void EnableScissorTest( Bool bEnableScissorTest );
+
+ void SetBlendState(const BlendStateDesc &BSDsc, const float *BlendFactors, Uint32 SampleMask);
+
+ Bool GetDepthWritesEnabled(){ return m_DepthWritesEnableState; }
+ Bool GetScissorTestEnabled(){ return m_RSState.ScissorTestEnable; }
+ void GetColorWriteMask( Uint32 RTIndex, Uint32 &WriteMask, Bool &bIsIndependent );
+ void SetColorWriteMask( Uint32 RTIndex, Uint32 WriteMask, Bool bIsIndependent );
+
+private:
+ // It is unsafe to use GL handle to keep track of bound objects
+ // When an object is released, GL is free to reuse its handle for
+ // the new created objects.
+ // Even using pointers is not safe as when an object is created,
+ // the system can reuse the same address
+ // The safest way is to keep global unique ID for all objects
+
+ Diligent::UniqueIdentifier m_GLProgId;
+ Diligent::UniqueIdentifier m_GLPipelineId;
+ Diligent::UniqueIdentifier m_VAOId;
+ Diligent::UniqueIdentifier m_FBOId;
+ std::vector< Diligent::UniqueIdentifier > m_BoundTextures;
+ std::vector< Diligent::UniqueIdentifier > m_BoundSamplers;
+ struct BoundImageInfo
+ {
+ Diligent::UniqueIdentifier InterfaceID;
+ GLint MipLevel;
+ GLboolean IsLayered;
+ GLint Layer;
+ GLenum Access;
+ GLenum Format;
+
+ BoundImageInfo( Diligent::UniqueIdentifier _UniqueID = 0,
+ GLint _MipLevel = 0,
+ GLboolean _IsLayered = 0,
+ GLint _Layer = 0,
+ GLenum _Access = 0,
+ GLenum _Format = 0) :
+ InterfaceID (_UniqueID ),
+ MipLevel (_MipLevel ),
+ IsLayered (_IsLayered),
+ Layer (_Layer ),
+ Access (_Access ),
+ Format (_Format )
+ {}
+
+ bool operator==(const BoundImageInfo &rhs)const
+ {
+ return InterfaceID == rhs.InterfaceID &&
+ MipLevel == rhs.MipLevel &&
+ IsLayered == rhs.IsLayered &&
+ Layer == rhs.Layer &&
+ Access == rhs.Access &&
+ Format == rhs.Format;
+ }
+ };
+ std::vector< BoundImageInfo > m_pBoundImages;
+ Uint32 m_PendingMemoryBarriers;
+
+ class EnableStateHelper
+ {
+ public:
+ enum class ENABLE_STATE
+ {
+ UNKNOWN,
+ ENABLED,
+ DISABLED
+ };
+
+ EnableStateHelper() : m_EnableState( ENABLE_STATE::UNKNOWN ) {}
+ bool operator == (bool bEnabled)const
+ {
+ return bEnabled && m_EnableState == ENABLE_STATE::ENABLED ||
+ !bEnabled && m_EnableState == ENABLE_STATE::DISABLED;
+ }
+ bool operator != (bool bEnabled) const
+ {
+ return !(*this == bEnabled);
+ }
+
+ const EnableStateHelper& operator = (bool bEnabled)
+ {
+ m_EnableState = bEnabled ? ENABLE_STATE::ENABLED : ENABLE_STATE::DISABLED;
+ return *this;
+ }
+
+ operator bool()const
+ {
+ return m_EnableState == ENABLE_STATE::ENABLED;
+ }
+
+ private:
+ ENABLE_STATE m_EnableState;
+ };
+ EnableStateHelper m_DepthEnableState;
+ EnableStateHelper m_DepthWritesEnableState;
+ COMPARISON_FUNCTION m_DepthCmpFunc;
+ EnableStateHelper m_StencilTestEnableState;
+ Uint8 m_StencilReadMask;
+ Uint8 m_StencilWriteMask;
+ struct StencilOpState
+ {
+ COMPARISON_FUNCTION Func;
+ STENCIL_OP StencilFailOp;
+ STENCIL_OP StencilDepthFailOp;
+ STENCIL_OP StencilPassOp;
+ Int32 Ref;
+ Uint32 Mask;
+ StencilOpState() :
+ Func( COMPARISON_FUNC_UNKNOW ),
+ StencilFailOp(STENCIL_OP_UNDEFINED),
+ StencilDepthFailOp( STENCIL_OP_UNDEFINED ),
+ StencilPassOp( STENCIL_OP_UNDEFINED ),
+ Ref( -1 ),
+ Mask( -1 )
+ {}
+ }m_StencilOpState[2];
+
+ struct RasterizerGLState
+ {
+ FILL_MODE FillMode;
+ CULL_MODE CullMode;
+ EnableStateHelper FrontCounterClockwise;
+ float fDepthBias;
+ float fSlopeScaledDepthBias;
+ EnableStateHelper DepthClampEnable;
+ EnableStateHelper ScissorTestEnable;
+ RasterizerGLState() :
+ FillMode(FILL_MODE_UNDEFINED),
+ CullMode(CULL_MODE_UNDEFINED),
+ fDepthBias( std::numeric_limits<float>::max() ),
+ fSlopeScaledDepthBias( std::numeric_limits<float>::max() )
+ {}
+ }m_RSState;
+
+ struct ContextCaps
+ {
+ bool bFillModeSelectionSupported;
+ GLint m_iMaxCombinedTexUnits;
+ ContextCaps() :
+ bFillModeSelectionSupported(True),
+ m_iMaxCombinedTexUnits(0)
+ {}
+ }m_Caps;
+
+ Uint32 m_ColorWriteMasks[MaxRenderTargets];
+ EnableStateHelper m_bIndependentWriteMasks;
+ Int32 m_iActiveTexture;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLContextWindows.h b/Graphics/GraphicsEngineOpenGL/include/GLContextWindows.h
new file mode 100644
index 00000000..a134d831
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/GLContextWindows.h
@@ -0,0 +1,49 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+namespace Diligent
+{
+
+ struct ContextInitInfo
+ {
+ SwapChainDesc SwapChainAttribs;
+ void *pNativeWndHandle;
+ };
+
+ class GLContext
+ {
+ public:
+ GLContext( const ContextInitInfo &Info, struct DeviceCaps &DeviceCaps );
+ ~GLContext();
+ void SwapBuffers();
+
+ const SwapChainDesc& GetSwapChainDesc(){ return m_SwapChainAttribs; }
+
+ private:
+ HGLRC m_Context;
+ HDC m_WindowHandleToDeviceContext;
+ SwapChainDesc m_SwapChainAttribs;
+ };
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLObjectWrapper.h b/Graphics/GraphicsEngineOpenGL/include/GLObjectWrapper.h
new file mode 100644
index 00000000..21710d4f
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/GLObjectWrapper.h
@@ -0,0 +1,195 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "UniqueIdentifier.h"
+
+namespace GLObjectWrappers
+{
+
+template<class CreateReleaseHelperType>
+class GLObjWrapper
+{
+public:
+ GLObjWrapper(bool CreateObject, CreateReleaseHelperType CreateReleaseHelper = CreateReleaseHelperType()) :
+ m_uiHandle(0),
+ m_CreateReleaseHelper(CreateReleaseHelper)
+ {
+ if( CreateObject )
+ {
+ Create();
+ if(!m_uiHandle)
+ {
+ std::string ErrorStr("Failed to create ");
+ ErrorStr += m_CreateReleaseHelper.Name;
+ ErrorStr += " object";
+ LOG_ERROR_AND_THROW(ErrorStr.c_str());
+ }
+ }
+ }
+
+ ~GLObjWrapper()
+ {
+ Release();
+ }
+
+ GLObjWrapper(GLObjWrapper&& Wrapper) :
+ m_uiHandle(Wrapper.m_uiHandle),
+ m_CreateReleaseHelper( std::move( Wrapper.m_CreateReleaseHelper ) ),
+ m_UniqueId( std::move(Wrapper.m_UniqueId) )
+ {
+ Wrapper.m_uiHandle = 0;
+ }
+
+ GLObjWrapper& operator = (GLObjWrapper&& Wrapper)
+ {
+ Release();
+ m_uiHandle = Wrapper.m_uiHandle;
+ Wrapper.m_uiHandle = 0;
+ m_CreateReleaseHelper = std::move( Wrapper.m_CreateReleaseHelper );
+ m_UniqueId = std::move(Wrapper.m_UniqueId);
+ return *this;
+ }
+
+ void Create()
+ {
+ VERIFY(m_uiHandle == 0, "GL object is already initialized");
+ Release();
+ m_CreateReleaseHelper.Create(m_uiHandle);
+ VERIFY(m_uiHandle, "Failed to initialize GL object" );
+ }
+
+ void Release()
+ {
+ if( m_uiHandle )
+ {
+ m_CreateReleaseHelper.Release(m_uiHandle);
+ m_uiHandle = 0;
+ }
+ }
+
+ Diligent::UniqueIdentifier GetUniqueID()const
+ {
+ // This unique ID is used to unambiguously identify the object for
+ // tracking purposes.
+ // Niether GL handle nor pointer could be safely used for this purpose
+ // as both GL reuses released handles and the OS reuses released pointers
+ return m_UniqueId.GetID();
+ }
+
+ operator GLuint()const{return m_uiHandle;}
+
+private:
+ GLObjWrapper(const GLObjWrapper&);
+ GLObjWrapper& operator = (const GLObjWrapper&);
+
+ GLuint m_uiHandle;
+ CreateReleaseHelperType m_CreateReleaseHelper;
+
+ // Have separate counter for every type of wrappers
+ Diligent::UniqueIdHelper<CreateReleaseHelperType> m_UniqueId;
+};
+
+class GLBufferObjCreateReleaseHelper
+{
+public:
+ static void Create(GLuint &BuffObj){ glGenBuffers (1, &BuffObj); }
+ static void Release(GLuint BuffObj){ glDeleteBuffers(1, &BuffObj); }
+ static const char *Name;
+};
+typedef GLObjWrapper<GLBufferObjCreateReleaseHelper> GLBufferObj;
+
+
+class GLProgramObjCreateReleaseHelper
+{
+public:
+ static void Create(GLuint &ProgObj){ ProgObj = glCreateProgram(); }
+ static void Release(GLuint ProgObj){ glDeleteProgram(ProgObj); }
+ static const char *Name;
+};
+typedef GLObjWrapper<GLProgramObjCreateReleaseHelper> GLProgramObj;
+
+
+class GLShaderObjCreateReleaseHelper
+{
+public:
+ GLShaderObjCreateReleaseHelper(GLenum ShaderType) : m_ShaderType(ShaderType){}
+ void Create(GLuint &ShaderObj){ ShaderObj = glCreateShader(m_ShaderType); }
+ void Release(GLuint ShaderObj){ glDeleteShader(ShaderObj); }
+ static const char *Name;
+private:
+ GLenum m_ShaderType;
+};
+typedef GLObjWrapper<GLShaderObjCreateReleaseHelper> GLShaderObj;
+
+
+class GLPipelineObjCreateReleaseHelper
+{
+public:
+ void Create(GLuint &Pipeline) { glGenProgramPipelines(1, &Pipeline); }
+ void Release(GLuint Pipeline) { glDeleteProgramPipelines(1, &Pipeline); }
+ static const char *Name;
+};
+typedef GLObjWrapper<GLPipelineObjCreateReleaseHelper> GLPipelineObj;
+
+
+class GLVAOCreateReleaseHelper
+{
+public:
+ void Create(GLuint &VAO) { glGenVertexArrays(1, &VAO); }
+ void Release(GLuint VAO) { glDeleteVertexArrays(1, &VAO); }
+ static const char *Name;
+};
+typedef GLObjWrapper<GLVAOCreateReleaseHelper> GLVertexArrayObj;
+
+
+class GLTextureCreateReleaseHelper
+{
+public:
+ void Create(GLuint &Tex) { glGenTextures(1, &Tex); }
+ void Release(GLuint Tex) { glDeleteTextures(1, &Tex); }
+ static const char *Name;
+};
+typedef GLObjWrapper<GLTextureCreateReleaseHelper> GLTextureObj;
+
+class GLSamplerCreateReleaseHelper
+{
+public:
+ void Create(GLuint &Sampler) { glGenSamplers(1, &Sampler); }
+ void Release(GLuint Sampler) { glDeleteSamplers(1, &Sampler); }
+ static const char *Name;
+};
+typedef GLObjWrapper<GLSamplerCreateReleaseHelper> GLSamplerObj;
+
+
+class GLFBOCreateReleaseHelper
+{
+public:
+ void Create(GLuint &FBO) { glGenFramebuffers(1, &FBO); }
+ void Release(GLuint FBO) { glDeleteFramebuffers(1, &FBO); }
+ static const char *Name;
+};
+typedef GLObjWrapper<GLFBOCreateReleaseHelper> GLFrameBufferObj;
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLProgram.h b/Graphics/GraphicsEngineOpenGL/include/GLProgram.h
new file mode 100644
index 00000000..96206374
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/GLProgram.h
@@ -0,0 +1,114 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+#include "GLObjectWrapper.h"
+
+#ifdef _DEBUG
+# define VERIFY_RESOURCE_BINDINGS
+#endif
+
+namespace Diligent
+{
+
+ class GLProgram : public GLObjectWrappers::GLProgramObj
+ {
+ public:
+ GLProgram( bool CreateObject );
+ GLProgram( GLProgram&& Program );
+
+ void LoadUniforms();
+
+ struct GLProgramVariableBase
+ {
+ GLProgramVariableBase( const Char* _Name ) :
+ Name( _Name )
+ {}
+
+ String Name;
+ RefCntAutoPtr<IDeviceObject> pResource;
+ };
+
+ struct UniformBufferInfo : GLProgramVariableBase
+ {
+ UniformBufferInfo(const Char* _Name, GLint _Index) :
+ GLProgramVariableBase(_Name),
+ Index(_Index)
+ {}
+
+ GLuint Index;
+ };
+ std::vector<UniformBufferInfo>& GetUniformBlocks(){ return m_UniformBlocks; }
+
+ struct SamplerInfo : GLProgramVariableBase
+ {
+ SamplerInfo(const Char* _Name, GLint _Location, GLenum _Type) :
+ GLProgramVariableBase(_Name),
+ Location(_Location),
+ Type(_Type)
+ {}
+ GLint Location;
+ GLenum Type;
+ };
+ std::vector<SamplerInfo>& GetSamplers(){ return m_Samplers; }
+
+ struct ImageInfo : GLProgramVariableBase
+ {
+ ImageInfo(const Char* _Name, GLint _BindingPoint, GLenum _Type) :
+ GLProgramVariableBase(_Name),
+ BindingPoint(_BindingPoint),
+ Type(_Type)
+ {}
+
+ GLint BindingPoint;
+ GLenum Type;
+ };
+ std::vector<ImageInfo>& GetImages(){ return m_Images; }
+
+ struct StorageBlockInfo : GLProgramVariableBase
+ {
+ StorageBlockInfo(const Char* _Name, GLint _Binding) :
+ GLProgramVariableBase(_Name),
+ Binding(_Binding)
+ {}
+
+ GLint Binding;
+ };
+ std::vector<StorageBlockInfo>& GetStorageBlocks(){ return m_StorageBlocks; }
+
+ void BindResources(IResourceMapping *pResourceMapping, Uint32 Flags);
+
+#ifdef VERIFY_RESOURCE_BINDINGS
+ void dbgVerifyResourceBindings();
+#endif
+
+ private:
+ GLProgram( const GLProgram& Program );
+ const GLProgram& operator = (const GLProgram& Program);
+ std::vector<UniformBufferInfo> m_UniformBlocks;
+ std::vector< SamplerInfo > m_Samplers;
+ std::vector< ImageInfo > m_Images;
+ std::vector< StorageBlockInfo > m_StorageBlocks;
+ // When adding new member DO NOT FORGET TO UPDATE GLProgram( GLProgram&& Program )!!!
+ };
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions.h b/Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions.h
new file mode 100644
index 00000000..b83c29b2
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions.h
@@ -0,0 +1,957 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#ifndef _GLSL_DEFINITIONS_
+#define _GLSL_DEFINITIONS_
+
+#define GLSL
+
+#define float4 vec4
+#define float3 vec3
+#define float2 vec2
+
+#define int4 ivec4
+#define int3 ivec3
+#define int2 ivec2
+
+#define uint4 uvec4
+#define uint3 uvec3
+#define uint2 uvec2
+
+#define bool4 bvec4
+#define bool3 bvec3
+#define bool2 bvec2
+
+// OpenGL matrices in GLSL are always as column-major
+// (this is not related to how they are stored)
+#define float2x2 mat2x2
+#define float2x3 mat3x2
+#define float2x4 mat4x2
+
+#define float3x2 mat2x3
+#define float3x3 mat3x3
+#define float3x4 mat4x3
+
+#define float4x2 mat2x4
+#define float4x3 mat3x4
+#define float4x4 mat4x4
+#define matrix mat4x4
+
+#define static
+
+#define SamplerState int
+#define SamplerComparisonState int
+
+// https://www.opengl.org/wiki/Memory_Model#Incoherent_memory_access
+// Shared variable access uses the rules for incoherent memory access.
+// This means that the user must perform certain synchronization in
+// order to ensure that shared variables are visible.
+// At the same time, shared variables are all implicitly declared coherent,
+// so one don't need to (and can't) use that qualifier.
+#define groupshared shared
+
+#ifdef FRAGMENT_SHADER
+# define ddx dFdx
+# define ddy dFdy
+#else
+# define ddx(x) (x) // GLSL compiler fails when it sees derivatives
+# define ddy(x) (x) // in any shader but fragment
+#endif
+
+#define ddx_coarse ddx
+#define ddy_coarse ddy
+#define ddx_fine ddx
+#define ddy_fine ddy
+
+#define mul(a, b) ((a)*(b))
+#define frac fract
+#define atan2 atan
+#define rsqrt inversesqrt
+#define fmod mod
+#define lerp mix
+#define dst distance
+#define countbits bitCount
+#define firstbithigh findMSB
+#define firstbitlow findLSB
+#define reversebits bitfieldReverse
+
+float rcp( float x ){ return 1.0 / x; }
+vec2 rcp( vec2 x ){ return vec2(1.0,1.0) / x; }
+vec3 rcp( vec3 x ){ return vec3(1.0,1.0,1.0) / x; }
+vec4 rcp( vec4 x ){ return vec4(1.0,1.0,1.0,1.0) / x; }
+
+float saturate( float x ){ return clamp( x, 0.0, 1.0 ); }
+vec2 saturate( vec2 x ){ return clamp( x, vec2(0.0, 0.0), vec2(1.0, 1.0) ); }
+vec3 saturate( vec3 x ){ return clamp( x, vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0) ); }
+vec4 saturate( vec4 x ){ return clamp( x, vec4(0.0, 0.0, 0.0, 0.0), vec4(1.0, 1.0, 1.0, 1.0) ); }
+
+void sincos( float x, out float s, out float c ){ s = sin( x ); c = cos( x ); }
+void sincos( vec2 x, out vec2 s, out vec2 c ){ s = sin( x ); c = cos( x ); }
+void sincos( vec3 x, out vec3 s, out vec3 c ){ s = sin( x ); c = cos( x ); }
+void sincos( vec4 x, out vec4 s, out vec4 c ){ s = sin( x ); c = cos( x ); }
+
+
+// Bit conversion operations
+
+float asfloat( float x ){ return x; }
+vec2 asfloat( vec2 x ){ return x; }
+vec3 asfloat( vec3 x ){ return x; }
+vec4 asfloat( vec4 x ){ return x; }
+
+float asfloat( int x ){ return intBitsToFloat(x); }
+vec2 asfloat( ivec2 x ){ return intBitsToFloat(x); }
+vec3 asfloat( ivec3 x ){ return intBitsToFloat(x); }
+vec4 asfloat( ivec4 x ){ return intBitsToFloat(x); }
+
+float asfloat( uint x ){ return uintBitsToFloat(x); }
+vec2 asfloat( uvec2 x ){ return uintBitsToFloat(x); }
+vec3 asfloat( uvec3 x ){ return uintBitsToFloat(x); }
+vec4 asfloat( uvec4 x ){ return uintBitsToFloat(x); }
+
+
+int asint( int x ){ return x; }
+ivec2 asint( ivec2 x ){ return x; }
+ivec3 asint( ivec3 x ){ return x; }
+ivec4 asint( ivec4 x ){ return x; }
+
+int asint( uint x ){ return int(x); }
+ivec2 asint( uvec2 x ){ return ivec2(x); }
+ivec3 asint( uvec3 x ){ return ivec3(x); }
+ivec4 asint( uvec4 x ){ return ivec4(x); }
+
+int asint( float x ){ return floatBitsToInt(x); }
+ivec2 asint( vec2 x ){ return floatBitsToInt(x); }
+ivec3 asint( vec3 x ){ return floatBitsToInt(x); }
+ivec4 asint( vec4 x ){ return floatBitsToInt(x); }
+
+
+uint asuint( uint x ){ return x; }
+uvec2 asuint( uvec2 x ){ return x; }
+uvec3 asuint( uvec3 x ){ return x; }
+uvec4 asuint( uvec4 x ){ return x; }
+
+uint asuint( int x ){ return uint(x); }
+uvec2 asuint( ivec2 x ){ return uvec2(x); }
+uvec3 asuint( ivec3 x ){ return uvec3(x); }
+uvec4 asuint( ivec4 x ){ return uvec4(x); }
+
+uint asuint( float x ){ return floatBitsToUint(x); }
+uvec2 asuint( vec2 x ){ return floatBitsToUint(x); }
+uvec3 asuint( vec3 x ){ return floatBitsToUint(x); }
+uvec4 asuint( vec4 x ){ return floatBitsToUint(x); }
+
+
+float f16tof32( uint u1 )
+{
+ return unpackHalf2x16( u1 ).x;
+}
+vec2 f16tof32( uvec2 u2 )
+{
+ uint u2PackedHalf = (u2.x & 0x0ffffu) | ((u2.y & 0x0ffffu) << 16u);
+ return unpackHalf2x16( u2PackedHalf );
+}
+vec3 f16tof32( uvec3 u3 )
+{
+ return vec3( f16tof32( u3.xy ), f16tof32( u3.z ) );
+}
+vec4 f16tof32( uvec4 u4 )
+{
+ return vec4( f16tof32( u4.xy ), f16tof32( u4.zw ) );
+}
+float f16tof32( int i1 ){ return f16tof32( uint ( i1 ) ); }
+vec2 f16tof32( ivec2 i2 ){ return f16tof32( uvec2( i2 ) ); }
+vec3 f16tof32( ivec3 i3 ){ return f16tof32( uvec3( i3 ) ); }
+vec4 f16tof32( ivec4 i4 ){ return f16tof32( uvec4( i4 ) ); }
+
+uint f32tof16( float f )
+{
+ return packHalf2x16( vec2( f, 0.0 ) ) & 0x0ffffu;
+}
+uvec2 f32tof16( vec2 f2 )
+{
+ uint u2PackedHalf = packHalf2x16( f2 );
+ return uvec2( u2PackedHalf & 0x0ffffu, u2PackedHalf >> 16u );
+}
+uvec3 f32tof16( vec3 f3 )
+{
+ return uvec3( f32tof16( f3.xy ), f32tof16( f3.z ) );
+}
+uvec4 f32tof16( vec4 f4 )
+{
+ return uvec4( f32tof16( f4.xy ), f32tof16( f4.zw ) );
+}
+
+#ifndef GL_ES // double is not supported on GLES
+double asdouble(uint lowbits, uint highbits)
+{
+ return packDouble2x32( uvec2( lowbits, highbits ) );
+}
+#endif
+
+
+// Floating point functions
+
+bool isfinite( float x )
+{
+ return !isinf( x ) && !isnan( x );
+}
+
+bool2 isfinite( vec2 f2 )
+{
+ return bool2( isfinite( f2.x ), isfinite( f2.y ) );
+}
+
+bool3 isfinite( vec3 f3 )
+{
+ return bool3( isfinite( f3.xy ), isfinite( f3.z ) );
+}
+
+bool4 isfinite( vec4 f4 )
+{
+ return bool4( isfinite( f4.xyz ), isfinite( f4.w ) );
+}
+
+#ifndef GL_ES
+ float noise( float x ){ return noise1( x ); }
+ vec2 noise( vec2 x ){ return noise2( x ); }
+ vec3 noise( vec3 x ){ return noise3( x ); }
+ vec4 noise( vec4 x ){ return noise4( x ); }
+#else
+ float noise( float x ){ return 0.0; }
+ vec2 noise( vec2 x ){ return vec2(0.0, 0.0); }
+ vec3 noise( vec3 x ){ return vec3(0.0, 0.0, 0.0); }
+ vec4 noise( vec4 x ){ return vec4(0.0, 0.0, 0.0, 0.0); }
+#endif
+
+float log10( float x )
+{
+ return log( x ) / log( 10.0 );
+}
+vec2 log10( vec2 x )
+{
+ float _lg10 = log( 10.0 );
+ return log( x ) / vec2(_lg10, _lg10);
+}
+vec3 log10( vec3 x )
+{
+ float _lg10 = log( 10.0 );
+ return log( x ) / vec3(_lg10, _lg10, _lg10);
+}
+vec4 log10( vec4 x )
+{
+ float _lg10 = log( 10.0 );
+ return log( x ) / vec4(_lg10, _lg10, _lg10, _lg10);
+}
+
+
+#ifdef GL_ES
+# define mad(a,b,c) ((a)*(b)+(c))
+#else
+# define mad fma
+#endif
+
+
+// Relational and logical operators
+#define Less lessThan
+#define LessEqual lessThanEqual
+#define Greater greaterThan
+#define GreaterEqual greaterThanEqual
+#define Equal equal
+#define NotEqual notEqual
+#define Not not
+bool4 And(bool4 L, bool4 R)
+{
+ return bool4(L.x && R.x,
+ L.y && R.y,
+ L.z && R.z,
+ L.w && R.w);
+}
+bool3 And(bool3 L, bool3 R)
+{
+ return bool3(L.x && R.x,
+ L.y && R.y,
+ L.z && R.z);
+}
+bool2 And(bool2 L, bool2 R)
+{
+ return bool2(L.x && R.x,
+ L.y && R.y);
+}
+bool And(bool L, bool R)
+{
+ return (L && R);
+}
+
+
+bool4 Or(bool4 L, bool4 R)
+{
+ return bool4(L.x || R.x,
+ L.y || R.y,
+ L.z || R.z,
+ L.w || R.w);
+}
+bool3 Or(bool3 L, bool3 R)
+{
+ return bool3(L.x || R.x,
+ L.y || R.y,
+ L.z || R.z);
+}
+bool2 Or(bool2 L, bool2 R)
+{
+ return bool2(L.x || R.x,
+ L.y || R.y);
+}
+bool Or(bool L, bool R)
+{
+ return (L || R);
+}
+
+float4 BoolToFloat( bool4 b4 )
+{
+ return float4(b4.x ? 1.0 : 0.0,
+ b4.y ? 1.0 : 0.0,
+ b4.z ? 1.0 : 0.0,
+ b4.w ? 1.0 : 0.0);
+}
+float3 BoolToFloat( bool3 b3 )
+{
+ return float3(b3.x ? 1.0 : 0.0,
+ b3.y ? 1.0 : 0.0,
+ b3.z ? 1.0 : 0.0);
+}
+float2 BoolToFloat( bool2 b2 )
+{
+ return float2(b2.x ? 1.0 : 0.0,
+ b2.y ? 1.0 : 0.0);
+}
+float BoolToFloat( bool b )
+{
+ return b ? 1.0 : 0.0;
+}
+
+
+// Synchronization functions
+
+#ifdef COMPUTE_SHADER
+
+// https://www.opengl.org/wiki/Memory_Model#Incoherent_memory_access
+
+// MSDN: GroupMemoryBarrier() blocks execution of all threads
+// in a group until all group SHARED accesses have been completed.
+void GroupMemoryBarrier()
+{
+ // OpenGL.org: groupMemoryBarrier() waits on the completion of all memory accesses
+ // performed by an invocation of a compute shader relative to the same access performed
+ // by other invocations in the same work group and then returns with no other effect.
+
+ // groupMemoryBarrier() acts like memoryBarrier(), ordering memory writes for all kinds
+ // of variables, but it only orders read/writes for the current work group.
+ groupMemoryBarrier();
+
+ // OpenGL.org: memoryBarrierShared() waits on the completion of
+ // all memory accesses resulting from the use of SHARED variables
+ // and then returns with no other effect.
+ memoryBarrierShared();
+}
+
+// MSDN: GroupMemoryBarrierWithGroupSync() blocks execution of all
+// threads in a group until all memory accesses have been completed
+// and all threads in the group have reached this call.
+void GroupMemoryBarrierWithGroupSync()
+{
+ // Issue memory barrier first!
+ GroupMemoryBarrier();
+ barrier();
+}
+
+// MSDN: DeviceMemoryBarrier() blocks execution of all threads
+// in a group until all device memory accesses have been completed.
+void DeviceMemoryBarrier()
+{
+ // Call all memory barriers except for shared memory
+
+ // Do we need to call groupMemoryBarrier() ?????
+
+ // OpenGL.org: memoryBarrierBuffer() waits on the completion of
+ // all memory accesses resulting from the use of BUFFER variables
+ // and then returns with no other effect
+ memoryBarrierBuffer();
+
+ // OpenGL.org: memoryBarrierImage() waits on the completion of all
+ // memory accesses resulting from the use of IMAGE variables and then
+ // returns with no other effect.
+ memoryBarrierImage();
+
+ // OpenGL.org: memoryBarrierAtomicCounter() waits on the completion of
+ // all accesses resulting from the use of ATOMIC COUNTERS and then returns
+ // with no other effect.
+ memoryBarrierAtomicCounter();
+}
+
+// MSDN: DeviceMemoryBarrierWithGroupSync() blocks execution of
+// all threads in a group until all device memory accesses have
+// been completed and all threads in the group have reached this call.
+void DeviceMemoryBarrierWithGroupSync()
+{
+ DeviceMemoryBarrier();
+ barrier();
+}
+
+// MSDN: AllMemoryBarrier() blocks execution of all threads in a
+// group until all memory accesses have been completed.
+void AllMemoryBarrier()
+{
+ // OpenGL.org: memoryBarrier() waits on the completion of ALL
+ // memory accesses resulting from the use of IMAGE variables or
+ // ATOMIC COUNTERS and then returns with no other effect.
+ memoryBarrier();
+ // NOTE: nothing is said about buffer memory and shared memory,
+ // so call memoryBarrierBuffer() and memoryBarrierShared() for safety
+
+ // OpenGL.org: memoryBarrierBuffer() waits on the completion of
+ // all memory accesses resulting from the use of BUFFER variables
+ // and then returns with no other effect
+ memoryBarrierBuffer();
+
+ // OpenGL.org: memoryBarrierShared() waits on the completion of
+ // all memory accesses resulting from the use of SHARED variables
+ // and then returns with no other effect.
+ memoryBarrierShared();
+
+ // Call all memory barrier functions. They should have no effect
+ // if everything is synchronized.
+
+ // OpenGL.org: memoryBarrierImage() waits on the completion of all
+ // memory accesses resulting from the use of IMAGE variables and then
+ // returns with no other effect.
+ memoryBarrierImage();
+
+ // OpenGL.org: memoryBarrierAtomicCounter() waits on the completion of
+ // all accesses resulting from the use of ATOMIC COUNTERS and then returns
+ // with no other effect.
+ memoryBarrierAtomicCounter();
+
+ // groupMemoryBarrier waits on the completion of all memory accesses performed
+ // by an invocation of a compute shader relative to the same access performed by
+ // other invocations in the same work group and then returns with no other effect.
+ groupMemoryBarrier();
+}
+
+// MSDN: AllMemoryBarrierWithGroupSync() blocks execution of all
+// threads in a group until all memory accesses have been completed
+// and all threads in the group have reached this call.
+void AllMemoryBarrierWithGroupSync()
+{
+ AllMemoryBarrier();
+ barrier();
+}
+
+#else
+
+void AllMemoryBarrier(){}
+void AllMemoryBarrierWithGroupSync(){}
+void DeviceMemoryBarrier(){}
+void DeviceMemoryBarrierWithGroupSync(){}
+void GroupMemoryBarrier(){}
+void GroupMemoryBarrierWithGroupSync(){}
+
+#endif
+
+
+// Type conversion functions
+
+vec4 _ExpandVector( float x ){ return vec4( x, x, x, x ); }
+vec4 _ExpandVector( vec2 f2 ){ return vec4( f2.x, f2.y, 0.0, 1.0 ); }
+vec4 _ExpandVector( vec3 f3 ){ return vec4( f3.x, f3.y, f3.z, 1.0 ); }
+vec4 _ExpandVector( vec4 f4 ){ return vec4( f4.x, f4.y, f4.z, f4.w ); }
+
+ivec4 _ExpandVector( int x ){ return ivec4( x, x, x, x ); }
+ivec4 _ExpandVector( ivec2 i2 ){ return ivec4( i2.x, i2.y, 0, 0 ); }
+ivec4 _ExpandVector( ivec3 i3 ){ return ivec4( i3.x, i3.y, i3.z, 0 ); }
+ivec4 _ExpandVector( ivec4 i4 ){ return ivec4( i4.x, i4.y, i4.z, i4.w ); }
+
+uvec4 _ExpandVector( uint x ){ return uvec4( x, x, x, x ); }
+uvec4 _ExpandVector( uvec2 u2 ){ return uvec4( u2.x, u2.y, 0u, 0u ); }
+uvec4 _ExpandVector( uvec3 u3 ){ return uvec4( u3.x, u3.y, u3.z, 0u ); }
+uvec4 _ExpandVector( uvec4 u4 ){ return uvec4( u4.x, u4.y, u4.z, u4.w ); }
+
+bvec4 _ExpandVector( bool x ){ return bvec4( x, x, x, x ); }
+bvec4 _ExpandVector( bvec2 b2 ){ return bvec4( b2.x, b2.y, false, false ); }
+bvec4 _ExpandVector( bvec3 b3 ){ return bvec4( b3.x, b3.y, b3.z, false ); }
+bvec4 _ExpandVector( bvec4 b4 ){ return bvec4( b4.x, b4.y, b4.z, b4.w ); }
+
+
+void _TypeConvertStore( out float Dst, in int Src ){ Dst = float( Src ); }
+void _TypeConvertStore( out float Dst, in uint Src ){ Dst = float( Src ); }
+void _TypeConvertStore( out float Dst, in float Src ){ Dst = float( Src ); }
+void _TypeConvertStore( out uint Dst, in int Src ){ Dst = uint( Src ); }
+void _TypeConvertStore( out uint Dst, in uint Src ){ Dst = uint( Src ); }
+void _TypeConvertStore( out uint Dst, in float Src ){ Dst = uint( Src ); }
+void _TypeConvertStore( out int Dst, in int Src ){ Dst = int( Src ); }
+void _TypeConvertStore( out int Dst, in uint Src ){ Dst = int( Src ); }
+void _TypeConvertStore( out int Dst, in float Src ){ Dst = int( Src ); }
+
+int _ToInt( int x ) { return int(x); }
+int _ToInt( uint x ) { return int(x); }
+int _ToInt( float x ){ return int(x); }
+int _ToInt( bool x ) { return x ? 1 : 0; }
+
+float _ToFloat( int x ) { return float(x); }
+float _ToFloat( uint x ) { return float(x); }
+float _ToFloat( float x ){ return float(x); }
+float _ToFloat( bool x ) { return x ? 1.0 : 0.0;}
+
+uint _ToUint( int x ) { return uint(x); }
+uint _ToUint( uint x ) { return uint(x); }
+uint _ToUint( float x ){ return uint(x); }
+uint _ToUint( bool x ) { return x ? 1u : 0u; }
+
+bool _ToBool( int x ) { return x != 0 ? true : false; }
+bool _ToBool( uint x ) { return x != 0u ? true : false; }
+bool _ToBool( float x ){ return x != 0.0 ? true : false; }
+bool _ToBool( bool x ) { return x; }
+
+#define _ToVec2(x,y) vec2(_ToFloat(x), _ToFloat(y))
+#define _ToVec3(x,y,z) vec3(_ToFloat(x), _ToFloat(y), _ToFloat(z))
+#define _ToVec4(x,y,z,w) vec4(_ToFloat(x), _ToFloat(y), _ToFloat(z), _ToFloat(w))
+
+#define _ToIvec2(x,y) ivec2(_ToInt(x), _ToInt(y))
+#define _ToIvec3(x,y,z) ivec3(_ToInt(x), _ToInt(y), _ToInt(z))
+#define _ToIvec4(x,y,z,w) ivec4(_ToInt(x), _ToInt(y), _ToInt(z), _ToInt(w))
+
+#define _ToUvec2(x,y) uvec2(_ToUint(x), _ToUint(y))
+#define _ToUvec3(x,y,z) uvec3(_ToUint(x), _ToUint(y), _ToUint(z))
+#define _ToUvec4(x,y,z,w) uvec4(_ToUint(x), _ToUint(y), _ToUint(z), _ToUint(w))
+
+#define _ToBvec2(x,y) bvec2(_ToBool(x), _ToBool(y))
+#define _ToBvec3(x,y,z) bvec3(_ToBool(x), _ToBool(y), _ToBool(z))
+#define _ToBvec4(x,y,z,w) bvec4(_ToBool(x), _ToBool(y), _ToBool(z), _ToBool(w))
+
+
+int _ToIvec( uint u1 ){ return _ToInt( u1 ); }
+ivec2 _ToIvec( uvec2 u2 ){ return _ToIvec2( u2.x, u2.y ); }
+ivec3 _ToIvec( uvec3 u3 ){ return _ToIvec3( u3.x, u3.y, u3.z ); }
+ivec4 _ToIvec( uvec4 u4 ){ return _ToIvec4( u4.x, u4.y, u4.z, u4.w ); }
+
+int _ToIvec( int i1 ){ return i1; }
+ivec2 _ToIvec( ivec2 i2 ){ return i2; }
+ivec3 _ToIvec( ivec3 i3 ){ return i3; }
+ivec4 _ToIvec( ivec4 i4 ){ return i4; }
+
+int _ToIvec( float f1 ){ return _ToInt( f1 ); }
+ivec2 _ToIvec( vec2 f2 ){ return _ToIvec2( f2.x, f2.y ); }
+ivec3 _ToIvec( vec3 f3 ){ return _ToIvec3( f3.x, f3.y, f3.z ); }
+ivec4 _ToIvec( vec4 f4 ){ return _ToIvec4( f4.x, f4.y, f4.z, f4.w ); }
+
+
+float _ToVec( uint u1 ){ return _ToFloat(u1); }
+vec2 _ToVec( uvec2 u2 ){ return _ToVec2( u2.x, u2.y ); }
+vec3 _ToVec( uvec3 u3 ){ return _ToVec3( u3.x, u3.y, u3.z ); }
+vec4 _ToVec( uvec4 u4 ){ return _ToVec4( u4.x, u4.y, u4.z, u4.w ); }
+
+float _ToVec( int i1 ){ return _ToFloat(i1); }
+vec2 _ToVec( ivec2 i2 ){ return _ToVec2( i2.x, i2.y ); }
+vec3 _ToVec( ivec3 i3 ){ return _ToVec3( i3.x, i3.y, i3.z ); }
+vec4 _ToVec( ivec4 i4 ){ return _ToVec4( i4.x, i4.y, i4.z, i4.w ); }
+
+float _ToVec( float f1 ){ return f1; }
+vec2 _ToVec( vec2 f2 ){ return f2; }
+vec3 _ToVec( vec3 f3 ){ return f3; }
+vec4 _ToVec( vec4 f4 ){ return f4; }
+
+
+uint _ToUvec( uint u1 ){ return u1; }
+uvec2 _ToUvec( uvec2 u2 ){ return u2; }
+uvec3 _ToUvec( uvec3 u3 ){ return u3; }
+uvec4 _ToUvec( uvec4 u4 ){ return u4; }
+
+uint _ToUvec( int i1 ){ return _ToUint( i1 ); }
+uvec2 _ToUvec( ivec2 i2 ){ return _ToUvec2( i2.x, i2.y ); }
+uvec3 _ToUvec( ivec3 i3 ){ return _ToUvec3( i3.x, i3.y, i3.z ); }
+uvec4 _ToUvec( ivec4 i4 ){ return _ToUvec4( i4.x, i4.y, i4.z, i4.w ); }
+
+uint _ToUvec( float f1 ){ return _ToUint( f1 ); }
+uvec2 _ToUvec( vec2 f2 ){ return _ToUvec2( f2.x, f2.y ); }
+uvec3 _ToUvec( vec3 f3 ){ return _ToUvec3( f3.x, f3.y, f3.z ); }
+uvec4 _ToUvec( vec4 f4 ){ return _ToUvec4( f4.x, f4.y, f4.z, f4.w ); }
+
+
+// TEXTURE FUNCTION STUB MACROS
+// https://www.opengl.org/wiki/Sampler_(GLSL)
+
+
+// Texture size queries
+// https://www.opengl.org/sdk/docs/man/html/textureSize.xhtml
+// textureSize returns the dimensions of level lod (if present) of the texture bound to sampler.
+// The components in the return value are filled in, in order, with the width, height and depth
+// of the texture. For the array forms, the last component of the return value is the number of
+// layers in the texture array.
+
+//#if !(defined(DESKTOP_GL) && __VERSION__ >= 430)
+# define textureQueryLevels(x) 0 // Only supported on 4.3+
+//#endif
+
+#define GetTex1DDimensions_1(Sampler, Width)\
+{ \
+ _TypeConvertStore( Width, textureSize(Sampler, 0) );\
+}
+
+#define GetTex1DDimensions_3(Sampler, MipLevel, Width, NumberOfMipLevels)\
+{ \
+ _TypeConvertStore( Width, textureSize(Sampler, _ToInt(MipLevel)) ); \
+ _TypeConvertStore( NumberOfMipLevels, textureQueryLevels(Sampler) ); \
+}
+
+#define GetTex1DArrDimensions_2(Sampler, Width, Elements)\
+{ \
+ ivec2 i2Size = textureSize(Sampler, 0); \
+ _TypeConvertStore( Width, i2Size.x );\
+ _TypeConvertStore( Elements, i2Size.y );\
+}
+
+#define GetTex1DArrDimensions_4(Sampler, MipLevel, Width, Elements, NumberOfMipLevels)\
+{ \
+ ivec2 i2Size = textureSize(Sampler, _ToInt(MipLevel)); \
+ _TypeConvertStore( Width, i2Size.x ); \
+ _TypeConvertStore( Elements, i2Size.y ); \
+ _TypeConvertStore( NumberOfMipLevels, textureQueryLevels(Sampler) );\
+}
+
+#define GetTex2DDimensions_2(Sampler, Width, Height)\
+{ \
+ ivec2 i2Size = textureSize(Sampler, 0); \
+ _TypeConvertStore( Width, i2Size.x ); \
+ _TypeConvertStore( Height, i2Size.y ); \
+}
+
+#define GetTex2DDimensions_4(Sampler, MipLevel, Width, Height, NumberOfMipLevels)\
+{ \
+ ivec2 i2Size = textureSize(Sampler, _ToInt(MipLevel) ); \
+ _TypeConvertStore( Width, i2Size.x ); \
+ _TypeConvertStore( Height, i2Size.y ); \
+ _TypeConvertStore( NumberOfMipLevels, textureQueryLevels(Sampler) );\
+}
+
+#define GetTex2DArrDimensions_3(Sampler, Width, Height, Elements)\
+{ \
+ ivec3 i3Size = textureSize(Sampler, 0); \
+ _TypeConvertStore( Width, i3Size.x ); \
+ _TypeConvertStore( Height, i3Size.y ); \
+ _TypeConvertStore( Elements,i3Size.z ); \
+}
+
+#define GetTex2DArrDimensions_5(Sampler, MipLevel, Width, Height, Elements, NumberOfMipLevels)\
+{ \
+ ivec3 i3Size = textureSize(Sampler, _ToInt(MipLevel)); \
+ _TypeConvertStore( Width, i3Size.x ); \
+ _TypeConvertStore( Height, i3Size.y ); \
+ _TypeConvertStore( Elements, i3Size.z ); \
+ _TypeConvertStore( NumberOfMipLevels, textureQueryLevels(Sampler) );\
+}
+
+#define GetTex3DDimensions_3(Sampler, Width, Height, Depth)\
+{ \
+ ivec3 i3Size = textureSize(Sampler, 0); \
+ _TypeConvertStore( Width, i3Size.x ); \
+ _TypeConvertStore( Height, i3Size.y ); \
+ _TypeConvertStore( Depth, i3Size.z ); \
+}
+
+#define GetTex3DDimensions_5(Sampler, MipLevel, Width, Height, Depth, NumberOfMipLevels)\
+{ \
+ ivec3 i3Size = textureSize(Sampler, _ToInt(MipLevel)); \
+ _TypeConvertStore( Width, i3Size.x ); \
+ _TypeConvertStore( Height, i3Size.y ); \
+ _TypeConvertStore( Depth, i3Size.z ); \
+ _TypeConvertStore( NumberOfMipLevels, textureQueryLevels(Sampler) );\
+}
+
+#define GetTex2DMSDimensions_3(Sampler, Width, Height, NumberOfSamples)\
+{ \
+ ivec2 i2Size = textureSize(Sampler); \
+ _TypeConvertStore( Width, i2Size.x ); \
+ _TypeConvertStore( Height, i2Size.y ); \
+ _TypeConvertStore( NumberOfSamples, 0 );\
+}
+
+#define GetTex2DMSArrDimensions_4(Sampler, Width, Height, Elements, NumberOfSamples)\
+{ \
+ ivec3 i3Size = textureSize(Sampler); \
+ _TypeConvertStore( Width, i3Size.x );\
+ _TypeConvertStore( Height, i3Size.y );\
+ _TypeConvertStore( Elements, i3Size.z );\
+ _TypeConvertStore( NumberOfSamples, 0 );\
+}
+
+
+// https://www.opengl.org/sdk/docs/man/html/imageSize.xhtml
+// imageSize returns the dimensions of the image bound to image. The components in the
+// return value are filled in, in order, with the width, height and depth of the image.
+// For the array forms, the last component of the return value is the number of layers
+// in the texture array.
+
+#define GetRWTex1DDimensions_1(Tex, Width)\
+{ \
+ _TypeConvertStore( Width, imageSize(Tex) ); \
+}
+
+#define GetRWTex1DArrDimensions_2(Tex, Width, Elements)\
+{ \
+ ivec2 i2Size = imageSize(Tex); \
+ _TypeConvertStore( Width, i2Size.x ); \
+ _TypeConvertStore( Elements, i2Size.y ); \
+}
+
+#define GetRWTex2DDimensions_2(Tex, Width, Height)\
+{ \
+ ivec2 i2Size = imageSize(Tex); \
+ _TypeConvertStore( Width, i2Size.x ); \
+ _TypeConvertStore( Height, i2Size.y ); \
+}
+
+#define GetRWTex2DArrDimensions_3(Tex, Width, Height, Elements)\
+{ \
+ ivec3 i3Size = imageSize(Tex); \
+ _TypeConvertStore( Width, i3Size.x );\
+ _TypeConvertStore( Height, i3Size.y );\
+ _TypeConvertStore( Elements, i3Size.z );\
+}
+
+#define GetRWTex3DDimensions_3(Tex, Width, Height, Depth)\
+{ \
+ ivec3 i3Size = imageSize(Tex); \
+ _TypeConvertStore( Width, i3Size.x ); \
+ _TypeConvertStore( Height, i3Size.y ); \
+ _TypeConvertStore( Depth, i3Size.z ); \
+}
+
+
+
+// Texture sampling operations
+
+
+// IMPORTANT NOTE ABOUT OFFSET
+// Offset parameter to all texture sampling functions must be a constant expression.
+// If it is not, the shader will be successfully compiled, HOWEVER the value of Offset
+// will silently be zero.
+//
+// A constant expression in GLSL is defined as follows:
+// * A literal value.
+// * A const-qualified variable with an explicit initializer (so not a function parameter).
+// * The result of the length() function of an array, but only if the array has an explicit size.
+// * The result of most operators, so long as all the operands are themselves constant expressions.
+// The operators not on this list are any assignment operators (+= and so forth), and the comma operator.
+// * The result of a constructor for a type, but only if all of the arguments to the constructor are
+// themselves constant expressions.
+// * The return value of any built-in function, but only if all of the arguments to the function are
+// themselves constant expressions. Opaque Types are never constant expressions. Note that the
+// functions dFdx, dFdy, and fwidth will return 0, when used in a context that requires a constant
+// expression (such as a const variable initializer).
+//
+// The list above does not include return value of a function, even when the value is compile-time expression.
+// As a result, we cannot use type conversion functions for Offset parameter.
+
+// In all texture sampling functions, the last component of Coords is used as Dsub and the array layer is specified
+// in the second to last component of Coords. (The second component of Coords is unused for 1D shadow lookups.)
+// For cube array textures, Dsub is specified as a separate parameter
+// mip
+#define SampleCmpLevel0Tex1D_3(Tex, Sampler, Coords, CompareValue) textureLod(Tex, _ToVec3((Coords).x, 0.0, CompareValue), 0.0)
+#define SampleCmpLevel0Tex1DArr_3(Tex, Sampler, Coords, CompareValue) textureLod(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue), 0.0)
+#define SampleCmpLevel0Tex2D_3(Tex, Sampler, Coords, CompareValue) textureLod(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue), 0.0)
+#define SampleCmpLevel0Tex2DArr_3(Tex, Sampler, Coords, CompareValue) 0.0 // No textureLod for sampler2DArrayShadow
+#define SampleCmpLevel0TexCube_3(Tex, Sampler, Coords, CompareValue) 0.0 // No textureLod for samplerCubeShadow
+#define SampleCmpLevel0TexCubeArr_3(Tex, Sampler, Coords, CompareValue) 0.0 // No textureLod for samplerCubeArrayShadow
+
+// mip
+#define SampleCmpLevel0Tex1D_4(Tex, Sampler, Coords, CompareValue, Offset) textureLodOffset(Tex, _ToVec3((Coords).x, 0.0, CompareValue), 0.0, int(Offset))
+#define SampleCmpLevel0Tex1DArr_4(Tex, Sampler, Coords, CompareValue, Offset) textureLodOffset(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue), 0.0, int(Offset))
+#define SampleCmpLevel0Tex2D_4(Tex, Sampler, Coords, CompareValue, Offset) textureLodOffset(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue), 0.0, ivec2((Offset).xy))
+#define SampleCmpLevel0Tex2DArr_4(Tex, Sampler, Coords, CompareValue, Offset) 0.0 // No textureLodOffset for sampler2DArrayShadow
+
+
+// https://www.opengl.org/sdk/docs/man/html/texture.xhtml - note: there are many mistakes on the page
+#ifdef FRAGMENT_SHADER
+
+# define Sample_2(Tex, Sampler, Coords) texture (Tex, _ToVec(Coords))
+# define Sample_3(Tex, Sampler, Coords, Offset) textureOffset(Tex, _ToVec(Coords), Offset)
+# define SampleBias_3(Tex, Sampler, Coords, Bias) texture (Tex, _ToVec(Coords), _ToFloat(Bias))
+# define SampleBias_4(Tex, Sampler, Coords, Bias, Offset) textureOffset(Tex, _ToVec(Coords), Offset, _ToFloat(Bias))
+
+# define SampleCmpTex1D_3(Tex, Sampler, Coords, CompareValue) texture(Tex, _ToVec3((Coords).x, 0.0, CompareValue))
+# define SampleCmpTex1DArr_3(Tex, Sampler, Coords, CompareValue) texture(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue))
+# define SampleCmpTex2D_3(Tex, Sampler, Coords, CompareValue) texture(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue))
+# define SampleCmpTex2DArr_3(Tex, Sampler, Coords, CompareValue) texture(Tex, _ToVec4((Coords).x, (Coords).y, (Coords).z, CompareValue))
+# define SampleCmpTexCube_3(Tex, Sampler, Coords, CompareValue) texture(Tex, _ToVec4((Coords).x, (Coords).y, (Coords).z, CompareValue))
+# define SampleCmpTexCubeArr_3(Tex, Sampler, Coords, CompareValue) texture(Tex, _ToVec4((Coords).x, (Coords).y, (Coords).z, (Coords).w), _ToFloat(CompareValue))
+
+# define SampleCmpTex1D_4(Tex, Sampler, Coords, CompareValue, Offset) textureOffset(Tex, _ToVec3((Coords).x, 0.0, CompareValue), int(Offset))
+# define SampleCmpTex1DArr_4(Tex, Sampler, Coords, CompareValue, Offset) textureOffset(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue), int(Offset))
+# define SampleCmpTex2D_4(Tex, Sampler, Coords, CompareValue, Offset) textureOffset(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue), ivec2((Offset).xy))
+# define SampleCmpTex2DArr_4(Tex, Sampler, Coords, CompareValue, Offset) textureOffset(Tex, _ToVec4((Coords).x, (Coords).y, (Coords).z, CompareValue), ivec2((Offset).xy))
+
+#else
+
+// Derivatives are only available in fragment shader. GLSL compiler fails when it
+// encounters texture() or textureOffset() instructions in other types of shaders. So
+// to let the shader be compiled and to have something meaningful, replace such operations
+// with textureLod() and textureLodOffset()
+
+# define Sample_2(Tex, Sampler, Coords) textureLod (Tex, _ToVec(Coords), 0.0)
+# define Sample_3(Tex, Sampler, Coords, Offset) textureLodOffset(Tex, _ToVec(Coords), 0.0, Offset)
+# define SampleBias_3(Tex, Sampler, Coords, Bias) textureLod (Tex, _ToVec(Coords), 0.0 + _ToFloat(Bias))
+# define SampleBias_4(Tex, Sampler, Coords, Bias, Offset) textureLodOffset(Tex, _ToVec(Coords), 0.0 + _ToFloat(Bias), Offset)
+
+# define SampleCmpTex1D_3 SampleCmpLevel0Tex1D_3
+# define SampleCmpTex1DArr_3 SampleCmpLevel0Tex1DArr_3
+# define SampleCmpTex2D_3 SampleCmpLevel0Tex2D_3
+# define SampleCmpTex2DArr_3 SampleCmpLevel0Tex2DArr_3
+# define SampleCmpTexCube_3 SampleCmpLevel0TexCube_3
+# define SampleCmpTexCubeArr_3 SampleCmpLevel0TexCubeArr_3
+
+# define SampleCmpTex1D_4 SampleCmpLevel0Tex1D_4
+# define SampleCmpTex1DArr_4 SampleCmpLevel0Tex1DArr_4
+# define SampleCmpTex2D_4 SampleCmpLevel0Tex2D_4
+# define SampleCmpTex2DArr_4 SampleCmpLevel0Tex2DArr_4
+
+#endif
+
+// https://www.opengl.org/sdk/docs/man/html/textureLod.xhtml
+#define SampleLevel_3(Tex, Sampler, Coords, Level) textureLod (Tex, _ToVec(Coords), _ToFloat(Level))
+#define SampleLevel_4(Tex, Sampler, Coords, Level, Offset) textureLodOffset(Tex, _ToVec(Coords), _ToFloat(Level), Offset)
+
+// https://www.opengl.org/sdk/docs/man/html/textureGrad.xhtml
+#define SampleGrad_4(Tex, Sampler, Coords, DDX, DDY) textureGrad (Tex, _ToVec(Coords), _ToVec(DDX), _ToVec(DDY))
+#define SampleGrad_5(Tex, Sampler, Coords, DDX, DDY, Offset) textureGradOffset(Tex, _ToVec(Coords), _ToVec(DDX), _ToVec(DDY), Offset)
+
+
+// texelFetch performs a lookup of a single texel from texture coordinate P in the texture
+// bound to sampler. The array layer is specified in the last component of P for array forms.
+// The lod parameter (if present) specifies the level-of-detail from which the texel will be fetched.
+// The sample specifies which sample within the texel will be returned when reading from a multi-sample texure.
+
+#define LoadTex1D_1(Tex, Location) texelFetch (Tex, _ToInt((Location).x), _ToInt((Location).y))
+#define LoadTex1D_2(Tex, Location, Offset)texelFetchOffset(Tex, _ToInt((Location).x), _ToInt((Location).y), int(Offset))
+#define LoadTex1DArr_1(Tex, Location) texelFetch (Tex, _ToIvec( (Location).xy), _ToInt((Location).z) )
+#define LoadTex1DArr_2(Tex, Location, Offset)texelFetchOffset(Tex, _ToIvec( (Location).xy), _ToInt((Location).z), int(Offset))
+#define LoadTex2D_1(Tex, Location) texelFetch (Tex, _ToIvec( (Location).xy), _ToInt((Location).z))
+#define LoadTex2D_2(Tex, Location, Offset)texelFetchOffset(Tex, _ToIvec( (Location).xy), _ToInt((Location).z), ivec2( (Offset).xy) )
+#define LoadTex2DArr_1(Tex, Location) texelFetch (Tex, _ToIvec( (Location).xyz), _ToInt((Location).w) )
+#define LoadTex2DArr_2(Tex, Location, Offset)texelFetchOffset(Tex, _ToIvec( (Location).xyz), _ToInt((Location).w), ivec2( (Offset).xy))
+#define LoadTex3D_1(Tex, Location) texelFetch (Tex, _ToIvec( (Location).xyz), _ToInt((Location).w))
+#define LoadTex3D_2(Tex, Location, Offset)texelFetchOffset(Tex, _ToIvec( (Location).xyz), _ToInt((Location).w), ivec3( (Offset).xyz))
+#define LoadTex2DMS_2(Tex, Location, Sample) texelFetch(Tex, _ToIvec( (Location).xy), _ToInt(Sample))
+#define LoadTex2DMS_3(Tex, Location, Sample, Offset)texelFetch(Tex, _ToIvec2( (Location).x + (Offset).x, (Location).y + (Offset).y), int(Sample) ) // No texelFetchOffset for texture2DMS
+#define LoadTex2DMSArr_2(Tex, Location, Sample) texelFetch(Tex, _ToIvec( (Location).xyz), _ToInt(Sample))
+#define LoadTex2DMSArr_3(Tex, Location, Sample, Offset)texelFetch(Tex, _ToIvec3( (Location).x + (Offset).x, (Location).y + (Offset).y, (Location).z), int(Sample)) // No texelFetchOffset for texture2DMSArray
+
+//https://www.opengl.org/sdk/docs/man/html/imageLoad.xhtml
+#define LoadRWTex1D_1(Tex, Location) imageLoad(Tex, _ToIvec((Location).x) )
+#define LoadRWTex1DArr_1(Tex, Location) imageLoad(Tex, _ToIvec((Location).xy) )
+#define LoadRWTex2D_1(Tex, Location) imageLoad(Tex, _ToIvec((Location).xy) )
+#define LoadRWTex2DArr_1(Tex, Location) imageLoad(Tex, _ToIvec((Location).xyz) )
+#define LoadRWTex3D_1(Tex, Location) imageLoad(Tex, _ToIvec((Location).xyz) )
+
+
+#define Gather_2(Tex, Sampler, Location) textureGather (Tex, _ToVec(Location))
+#define Gather_3(Tex, Sampler, Location, Offset)textureGatherOffset(Tex, _ToVec(Location), Offset)
+
+#define GatherCmp_3(Tex, Sampler, Location, CompareVal) textureGather (Tex, _ToVec(Location), _ToFloat(CompareVal))
+#define GatherCmp_4(Tex, Sampler, Location, CompareVal, Offset)textureGatherOffset(Tex, _ToVec(Location), _ToFloat(CompareVal), Offset)
+
+// Atomic operations
+#define InterlockedAddSharedVar_2(dest, value) atomicAdd(dest, value)
+#define InterlockedAddSharedVar_3(dest, value, orig_val) orig_val = atomicAdd(dest, value)
+#define InterlockedAddImage_2(img, coords, value) imageAtomicAdd(img, _ToIvec(coords), value)
+#define InterlockedAddImage_3(img, coords, value, orig_val)orig_val = imageAtomicAdd(img, _ToIvec(coords), value)
+
+#define InterlockedAndSharedVar_2(dest, value) atomicAnd(dest, value)
+#define InterlockedAndSharedVar_3(dest, value, orig_val) orig_val = atomicAnd(dest, value)
+#define InterlockedAndImage_2(img, coords, value) imageAtomicAnd(img, _ToIvec(coords), value)
+#define InterlockedAndImage_3(img, coords, value, orig_val)orig_val = imageAtomicAnd(img, _ToIvec(coords), value)
+
+#define InterlockedMaxSharedVar_2(dest, value) atomicMax(dest, value)
+#define InterlockedMaxSharedVar_3(dest, value, orig_val) orig_val = atomicMax(dest, value)
+#define InterlockedMaxImage_2(img, coords, value) imageAtomicMax(img, _ToIvec(coords), value)
+#define InterlockedMaxImage_3(img, coords, value, orig_val)orig_val = imageAtomicMax(img, _ToIvec(coords), value)
+
+#define InterlockedMinSharedVar_2(dest, value) atomicMin(dest, value)
+#define InterlockedMinSharedVar_3(dest, value, orig_val) orig_val = atomicMin(dest, value)
+#define InterlockedMinImage_2(img, coords, value) imageAtomicMin(img, _ToIvec(coords), value)
+#define InterlockedMinImage_3(img, coords, value, orig_val)orig_val = imageAtomicMin(img, _ToIvec(coords), value)
+
+#define InterlockedOrSharedVar_2(dest, value) atomicOr(dest, value)
+#define InterlockedOrSharedVar_3(dest, value, orig_val) orig_val = atomicOr(dest, value)
+#define InterlockedOrImage_2(img, coords, value) imageAtomicOr(img, _ToIvec(coords), value)
+#define InterlockedOrImage_3(img, coords, value, orig_val)orig_val = imageAtomicOr(img, _ToIvec(coords), value)
+
+#define InterlockedXorSharedVar_2(dest, value) atomicXor(dest, value)
+#define InterlockedXorSharedVar_3(dest, value, orig_val) orig_val = atomicXor(dest, value)
+#define InterlockedXorImage_2(img, coords, value) imageAtomicXor(img, _ToIvec(coords), value)
+#define InterlockedXorImage_3(img, coords, value, orig_val)orig_val = imageAtomicXor(img, _ToIvec(coords), value)
+
+// There is actually no InterlockedExchange() with 2 arguments
+#define InterlockedExchangeSharedVar_2(dest, value) atomicExchange(dest, value)
+#define InterlockedExchangeSharedVar_3(dest, value, orig_val) orig_val = atomicExchange(dest, value)
+#define InterlockedExchangeImage_2(img, coords, value) imageAtomicExchange(img, _ToIvec(coords), value)
+#define InterlockedExchangeImage_3(img, coords, value, orig_val)orig_val = imageAtomicExchange(img, _ToIvec(coords), value)
+
+//uint imageAtomicCompSwap( image img, IVec P, nint compare, nint data);
+//void InterlockedCompareExchange( in R dest, in T compare_value, in T value, out T original_value);
+#define InterlockedCompareExchangeSharedVar_4(dest, cmp_val, value, orig_val) orig_val = atomicCompSwap(dest, cmp_val, value)
+#define InterlockedCompareExchangeImage_4(img, coords, cmp_val, value, orig_val) orig_val = imageAtomicCompSwap(img, _ToIvec(coords), cmp_val, value)
+
+#define InterlockedCompareStoreSharedVar_3(dest, cmp_val, value) atomicCompSwap(dest, cmp_val, value)
+#define InterlockedCompareStoreImage_3(img, coords, cmp_val, value)imageAtomicCompSwap(img, _ToIvec(coords), cmp_val, value)
+
+
+// Swizzling macros
+#define _SWIZZLE0
+#define _SWIZZLE1 .x
+#define _SWIZZLE2 .xy
+#define _SWIZZLE3 .xyz
+#define _SWIZZLE4 .xyzw
+
+// Helper functions
+
+float2 NormalizedDeviceXYToTexUV( float2 f2ProjSpaceXY )
+{
+ return float2(0.5,0.5) + float2(0.5,0.5) * f2ProjSpaceXY.xy;
+}
+
+float NormalizedDeviceZToDepth(float fNDC_Z)
+{
+ return fNDC_Z * 0.5 + 0.5; // [-1, +1] -> [0, 1]
+}
+
+float DepthToNormalizedDeviceZ(float fDepth)
+{
+ return fDepth * 2.0 - 1.0; // [0, 1] -> [-1, +1]
+}
+
+#define F3NDC_XYZ_TO_UVD_SCALE float3(0.5, 0.5, 0.5)
+
+#define NDC_MIN_Z -1.0 // Minimal z in the normalized device space
+
+#define MATRIX_ELEMENT(mat, row, col) mat[col][row]
+
+#endif // _GLSL_DEFINITIONS_
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions_inc.h b/Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions_inc.h
new file mode 100644
index 00000000..bacbdb29
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions_inc.h
@@ -0,0 +1,957 @@
+"/* Copyright 2015 Egor Yusov\n"
+" * \n"
+" * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
+" * you may not use this file except in compliance with the License.\n"
+" * You may obtain a copy of the License at\n"
+" * \n"
+" * http://www.apache.org/licenses/LICENSE-2.0\n"
+" * \n"
+" * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
+" * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
+" * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.\n"
+" *\n"
+" * In no event and under no legal theory, whether in tort (including negligence), \n"
+" * contract, or otherwise, unless required by applicable law (such as deliberate \n"
+" * and grossly negligent acts) or agreed to in writing, shall any Contributor be\n"
+" * liable for any damages, including any direct, indirect, special, incidental, \n"
+" * or consequential damages of any character arising as a result of this License or \n"
+" * out of the use or inability to use the software (including but not limited to damages \n"
+" * for loss of goodwill, work stoppage, computer failure or malfunction, or any and \n"
+" * all other commercial damages or losses), even if such Contributor has been advised \n"
+" * of the possibility of such damages.\n"
+" */\n"
+"\n"
+"#ifndef _GLSL_DEFINITIONS_\n"
+"#define _GLSL_DEFINITIONS_\n"
+"\n"
+"#define GLSL\n"
+"\n"
+"#define float4 vec4\n"
+"#define float3 vec3\n"
+"#define float2 vec2\n"
+"\n"
+"#define int4 ivec4\n"
+"#define int3 ivec3\n"
+"#define int2 ivec2\n"
+"\n"
+"#define uint4 uvec4\n"
+"#define uint3 uvec3\n"
+"#define uint2 uvec2\n"
+"\n"
+"#define bool4 bvec4\n"
+"#define bool3 bvec3\n"
+"#define bool2 bvec2\n"
+"\n"
+"// OpenGL matrices in GLSL are always as column-major \n"
+"// (this is not related to how they are stored)\n"
+"#define float2x2 mat2x2\n"
+"#define float2x3 mat3x2\n"
+"#define float2x4 mat4x2\n"
+"\n"
+"#define float3x2 mat2x3\n"
+"#define float3x3 mat3x3\n"
+"#define float3x4 mat4x3\n"
+"\n"
+"#define float4x2 mat2x4\n"
+"#define float4x3 mat3x4\n"
+"#define float4x4 mat4x4\n"
+"#define matrix mat4x4\n"
+"\n"
+"#define static\n"
+"\n"
+"#define SamplerState int\n"
+"#define SamplerComparisonState int\n"
+"\n"
+"// https://www.opengl.org/wiki/Memory_Model#Incoherent_memory_access\n"
+"// Shared variable access uses the rules for incoherent memory access. \n"
+"// This means that the user must perform certain synchronization in \n"
+"// order to ensure that shared variables are visible.\n"
+"// At the same time, shared variables are all implicitly declared coherent, \n"
+"// so one don\'t need to (and can\'t) use that qualifier.\n"
+"#define groupshared shared\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"# define ddx dFdx\n"
+"# define ddy dFdy\n"
+"#else\n"
+"# define ddx(x) (x) // GLSL compiler fails when it sees derivatives \n"
+"# define ddy(x) (x) // in any shader but fragment\n"
+"#endif\n"
+"\n"
+"#define ddx_coarse ddx\n"
+"#define ddy_coarse ddy\n"
+"#define ddx_fine ddx\n"
+"#define ddy_fine ddy\n"
+"\n"
+"#define mul(a, b) ((a)*(b))\n"
+"#define frac fract\n"
+"#define atan2 atan\n"
+"#define rsqrt inversesqrt\n"
+"#define fmod mod\n"
+"#define lerp mix\n"
+"#define dst distance\n"
+"#define countbits bitCount\n"
+"#define firstbithigh findMSB\n"
+"#define firstbitlow findLSB\n"
+"#define reversebits bitfieldReverse\n"
+"\n"
+"float rcp( float x ){ return 1.0 / x; }\n"
+"vec2 rcp( vec2 x ){ return vec2(1.0,1.0) / x; }\n"
+"vec3 rcp( vec3 x ){ return vec3(1.0,1.0,1.0) / x; }\n"
+"vec4 rcp( vec4 x ){ return vec4(1.0,1.0,1.0,1.0) / x; }\n"
+"\n"
+"float saturate( float x ){ return clamp( x, 0.0, 1.0 ); }\n"
+"vec2 saturate( vec2 x ){ return clamp( x, vec2(0.0, 0.0), vec2(1.0, 1.0) ); }\n"
+"vec3 saturate( vec3 x ){ return clamp( x, vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0) ); }\n"
+"vec4 saturate( vec4 x ){ return clamp( x, vec4(0.0, 0.0, 0.0, 0.0), vec4(1.0, 1.0, 1.0, 1.0) ); }\n"
+"\n"
+"void sincos( float x, out float s, out float c ){ s = sin( x ); c = cos( x ); }\n"
+"void sincos( vec2 x, out vec2 s, out vec2 c ){ s = sin( x ); c = cos( x ); }\n"
+"void sincos( vec3 x, out vec3 s, out vec3 c ){ s = sin( x ); c = cos( x ); }\n"
+"void sincos( vec4 x, out vec4 s, out vec4 c ){ s = sin( x ); c = cos( x ); }\n"
+"\n"
+"\n"
+"// Bit conversion operations\n"
+"\n"
+"float asfloat( float x ){ return x; }\n"
+"vec2 asfloat( vec2 x ){ return x; }\n"
+"vec3 asfloat( vec3 x ){ return x; }\n"
+"vec4 asfloat( vec4 x ){ return x; }\n"
+"\n"
+"float asfloat( int x ){ return intBitsToFloat(x); }\n"
+"vec2 asfloat( ivec2 x ){ return intBitsToFloat(x); }\n"
+"vec3 asfloat( ivec3 x ){ return intBitsToFloat(x); }\n"
+"vec4 asfloat( ivec4 x ){ return intBitsToFloat(x); }\n"
+"\n"
+"float asfloat( uint x ){ return uintBitsToFloat(x); }\n"
+"vec2 asfloat( uvec2 x ){ return uintBitsToFloat(x); }\n"
+"vec3 asfloat( uvec3 x ){ return uintBitsToFloat(x); }\n"
+"vec4 asfloat( uvec4 x ){ return uintBitsToFloat(x); }\n"
+"\n"
+"\n"
+"int asint( int x ){ return x; }\n"
+"ivec2 asint( ivec2 x ){ return x; }\n"
+"ivec3 asint( ivec3 x ){ return x; }\n"
+"ivec4 asint( ivec4 x ){ return x; }\n"
+"\n"
+"int asint( uint x ){ return int(x); }\n"
+"ivec2 asint( uvec2 x ){ return ivec2(x); }\n"
+"ivec3 asint( uvec3 x ){ return ivec3(x); }\n"
+"ivec4 asint( uvec4 x ){ return ivec4(x); }\n"
+"\n"
+"int asint( float x ){ return floatBitsToInt(x); }\n"
+"ivec2 asint( vec2 x ){ return floatBitsToInt(x); }\n"
+"ivec3 asint( vec3 x ){ return floatBitsToInt(x); }\n"
+"ivec4 asint( vec4 x ){ return floatBitsToInt(x); }\n"
+"\n"
+"\n"
+"uint asuint( uint x ){ return x; }\n"
+"uvec2 asuint( uvec2 x ){ return x; }\n"
+"uvec3 asuint( uvec3 x ){ return x; }\n"
+"uvec4 asuint( uvec4 x ){ return x; }\n"
+"\n"
+"uint asuint( int x ){ return uint(x); }\n"
+"uvec2 asuint( ivec2 x ){ return uvec2(x); }\n"
+"uvec3 asuint( ivec3 x ){ return uvec3(x); }\n"
+"uvec4 asuint( ivec4 x ){ return uvec4(x); }\n"
+"\n"
+"uint asuint( float x ){ return floatBitsToUint(x); }\n"
+"uvec2 asuint( vec2 x ){ return floatBitsToUint(x); }\n"
+"uvec3 asuint( vec3 x ){ return floatBitsToUint(x); }\n"
+"uvec4 asuint( vec4 x ){ return floatBitsToUint(x); }\n"
+"\n"
+"\n"
+"float f16tof32( uint u1 )\n"
+"{ \n"
+" return unpackHalf2x16( u1 ).x; \n"
+"}\n"
+"vec2 f16tof32( uvec2 u2 )\n"
+"{ \n"
+" uint u2PackedHalf = (u2.x & 0x0ffffu) | ((u2.y & 0x0ffffu) << 16u);\n"
+" return unpackHalf2x16( u2PackedHalf ); \n"
+"}\n"
+"vec3 f16tof32( uvec3 u3 )\n"
+"{ \n"
+" return vec3( f16tof32( u3.xy ), f16tof32( u3.z ) );\n"
+"}\n"
+"vec4 f16tof32( uvec4 u4 )\n"
+"{ \n"
+" return vec4( f16tof32( u4.xy ), f16tof32( u4.zw ) );\n"
+"}\n"
+"float f16tof32( int i1 ){ return f16tof32( uint ( i1 ) ); }\n"
+"vec2 f16tof32( ivec2 i2 ){ return f16tof32( uvec2( i2 ) ); }\n"
+"vec3 f16tof32( ivec3 i3 ){ return f16tof32( uvec3( i3 ) ); }\n"
+"vec4 f16tof32( ivec4 i4 ){ return f16tof32( uvec4( i4 ) ); }\n"
+"\n"
+"uint f32tof16( float f )\n"
+"{ \n"
+" return packHalf2x16( vec2( f, 0.0 ) ) & 0x0ffffu; \n"
+"}\n"
+"uvec2 f32tof16( vec2 f2 )\n"
+"{ \n"
+" uint u2PackedHalf = packHalf2x16( f2 );\n"
+" return uvec2( u2PackedHalf & 0x0ffffu, u2PackedHalf >> 16u );\n"
+"}\n"
+"uvec3 f32tof16( vec3 f3 )\n"
+"{\n"
+" return uvec3( f32tof16( f3.xy ), f32tof16( f3.z ) );\n"
+"}\n"
+"uvec4 f32tof16( vec4 f4 )\n"
+"{\n"
+" return uvec4( f32tof16( f4.xy ), f32tof16( f4.zw ) );\n"
+"}\n"
+"\n"
+"#ifndef GL_ES // double is not supported on GLES\n"
+"double asdouble(uint lowbits, uint highbits)\n"
+"{\n"
+" return packDouble2x32( uvec2( lowbits, highbits ) );\n"
+"}\n"
+"#endif\n"
+"\n"
+"\n"
+"// Floating point functions\n"
+"\n"
+"bool isfinite( float x )\n"
+"{\n"
+" return !isinf( x ) && !isnan( x );\n"
+"}\n"
+"\n"
+"bool2 isfinite( vec2 f2 )\n"
+"{\n"
+" return bool2( isfinite( f2.x ), isfinite( f2.y ) );\n"
+"}\n"
+"\n"
+"bool3 isfinite( vec3 f3 )\n"
+"{\n"
+" return bool3( isfinite( f3.xy ), isfinite( f3.z ) );\n"
+"}\n"
+"\n"
+"bool4 isfinite( vec4 f4 )\n"
+"{\n"
+" return bool4( isfinite( f4.xyz ), isfinite( f4.w ) );\n"
+"}\n"
+"\n"
+"#ifndef GL_ES\n"
+" float noise( float x ){ return noise1( x ); }\n"
+" vec2 noise( vec2 x ){ return noise2( x ); }\n"
+" vec3 noise( vec3 x ){ return noise3( x ); }\n"
+" vec4 noise( vec4 x ){ return noise4( x ); }\n"
+"#else\n"
+" float noise( float x ){ return 0.0; }\n"
+" vec2 noise( vec2 x ){ return vec2(0.0, 0.0); }\n"
+" vec3 noise( vec3 x ){ return vec3(0.0, 0.0, 0.0); }\n"
+" vec4 noise( vec4 x ){ return vec4(0.0, 0.0, 0.0, 0.0); }\n"
+"#endif\n"
+"\n"
+"float log10( float x )\n"
+"{\n"
+" return log( x ) / log( 10.0 );\n"
+"}\n"
+"vec2 log10( vec2 x )\n"
+"{\n"
+" float _lg10 = log( 10.0 );\n"
+" return log( x ) / vec2(_lg10, _lg10);\n"
+"}\n"
+"vec3 log10( vec3 x )\n"
+"{\n"
+" float _lg10 = log( 10.0 );\n"
+" return log( x ) / vec3(_lg10, _lg10, _lg10);\n"
+"}\n"
+"vec4 log10( vec4 x )\n"
+"{\n"
+" float _lg10 = log( 10.0 );\n"
+" return log( x ) / vec4(_lg10, _lg10, _lg10, _lg10);\n"
+"}\n"
+"\n"
+"\n"
+"#ifdef GL_ES\n"
+"# define mad(a,b,c) ((a)*(b)+(c))\n"
+"#else\n"
+"# define mad fma\n"
+"#endif\n"
+"\n"
+"\n"
+"// Relational and logical operators\n"
+"#define Less lessThan\n"
+"#define LessEqual lessThanEqual\n"
+"#define Greater greaterThan\n"
+"#define GreaterEqual greaterThanEqual\n"
+"#define Equal equal\n"
+"#define NotEqual notEqual\n"
+"#define Not not\n"
+"bool4 And(bool4 L, bool4 R)\n"
+"{\n"
+" return bool4(L.x && R.x,\n"
+" L.y && R.y,\n"
+" L.z && R.z,\n"
+" L.w && R.w);\n"
+"}\n"
+"bool3 And(bool3 L, bool3 R)\n"
+"{\n"
+" return bool3(L.x && R.x,\n"
+" L.y && R.y,\n"
+" L.z && R.z);\n"
+"}\n"
+"bool2 And(bool2 L, bool2 R)\n"
+"{\n"
+" return bool2(L.x && R.x,\n"
+" L.y && R.y);\n"
+"}\n"
+"bool And(bool L, bool R)\n"
+"{\n"
+" return (L && R);\n"
+"}\n"
+"\n"
+"\n"
+"bool4 Or(bool4 L, bool4 R)\n"
+"{\n"
+" return bool4(L.x || R.x,\n"
+" L.y || R.y,\n"
+" L.z || R.z,\n"
+" L.w || R.w);\n"
+"}\n"
+"bool3 Or(bool3 L, bool3 R)\n"
+"{\n"
+" return bool3(L.x || R.x,\n"
+" L.y || R.y,\n"
+" L.z || R.z);\n"
+"}\n"
+"bool2 Or(bool2 L, bool2 R)\n"
+"{\n"
+" return bool2(L.x || R.x,\n"
+" L.y || R.y);\n"
+"}\n"
+"bool Or(bool L, bool R)\n"
+"{\n"
+" return (L || R);\n"
+"}\n"
+"\n"
+"float4 BoolToFloat( bool4 b4 )\n"
+"{\n"
+" return float4(b4.x ? 1.0 : 0.0,\n"
+" b4.y ? 1.0 : 0.0,\n"
+" b4.z ? 1.0 : 0.0,\n"
+" b4.w ? 1.0 : 0.0);\n"
+"}\n"
+"float3 BoolToFloat( bool3 b3 )\n"
+"{\n"
+" return float3(b3.x ? 1.0 : 0.0,\n"
+" b3.y ? 1.0 : 0.0,\n"
+" b3.z ? 1.0 : 0.0);\n"
+"}\n"
+"float2 BoolToFloat( bool2 b2 )\n"
+"{\n"
+" return float2(b2.x ? 1.0 : 0.0,\n"
+" b2.y ? 1.0 : 0.0);\n"
+"}\n"
+"float BoolToFloat( bool b )\n"
+"{\n"
+" return b ? 1.0 : 0.0;\n"
+"}\n"
+"\n"
+"\n"
+"// Synchronization functions\n"
+"\n"
+"#ifdef COMPUTE_SHADER\n"
+"\n"
+"// https://www.opengl.org/wiki/Memory_Model#Incoherent_memory_access\n"
+"\n"
+"// MSDN: GroupMemoryBarrier() blocks execution of all threads \n"
+"// in a group until all group SHARED accesses have been completed.\n"
+"void GroupMemoryBarrier()\n"
+"{\n"
+" // OpenGL.org: groupMemoryBarrier() waits on the completion of all memory accesses \n"
+" // performed by an invocation of a compute shader relative to the same access performed \n"
+" // by other invocations in the same work group and then returns with no other effect.\n"
+"\n"
+" // groupMemoryBarrier() acts like memoryBarrier(), ordering memory writes for all kinds \n"
+" // of variables, but it only orders read/writes for the current work group.\n"
+" groupMemoryBarrier();\n"
+"\n"
+" // OpenGL.org: memoryBarrierShared() waits on the completion of \n"
+" // all memory accesses resulting from the use of SHARED variables\n"
+" // and then returns with no other effect. \n"
+" memoryBarrierShared();\n"
+"}\n"
+"\n"
+"// MSDN: GroupMemoryBarrierWithGroupSync() blocks execution of all \n"
+"// threads in a group until all memory accesses have been completed \n"
+"// and all threads in the group have reached this call.\n"
+"void GroupMemoryBarrierWithGroupSync()\n"
+"{\n"
+" // Issue memory barrier first!\n"
+" GroupMemoryBarrier();\n"
+" barrier();\n"
+"}\n"
+"\n"
+"// MSDN: DeviceMemoryBarrier() blocks execution of all threads \n"
+"// in a group until all device memory accesses have been completed.\n"
+"void DeviceMemoryBarrier()\n"
+"{\n"
+" // Call all memory barriers except for shared memory\n"
+" \n"
+" // Do we need to call groupMemoryBarrier() ????? \n"
+"\n"
+" // OpenGL.org: memoryBarrierBuffer() waits on the completion of \n"
+" // all memory accesses resulting from the use of BUFFER variables \n"
+" // and then returns with no other effect\n"
+" memoryBarrierBuffer();\n"
+"\n"
+" // OpenGL.org: memoryBarrierImage() waits on the completion of all \n"
+" // memory accesses resulting from the use of IMAGE variables and then \n"
+" // returns with no other effect. \n"
+" memoryBarrierImage();\n"
+"\n"
+" // OpenGL.org: memoryBarrierAtomicCounter() waits on the completion of \n"
+" // all accesses resulting from the use of ATOMIC COUNTERS and then returns \n"
+" // with no other effect. \n"
+" memoryBarrierAtomicCounter();\n"
+"}\n"
+"\n"
+"// MSDN: DeviceMemoryBarrierWithGroupSync() blocks execution of \n"
+"// all threads in a group until all device memory accesses have \n"
+"// been completed and all threads in the group have reached this call.\n"
+"void DeviceMemoryBarrierWithGroupSync()\n"
+"{\n"
+" DeviceMemoryBarrier();\n"
+" barrier();\n"
+"}\n"
+"\n"
+"// MSDN: AllMemoryBarrier() blocks execution of all threads in a \n"
+"// group until all memory accesses have been completed.\n"
+"void AllMemoryBarrier()\n"
+"{\n"
+" // OpenGL.org: memoryBarrier() waits on the completion of ALL \n"
+" // memory accesses resulting from the use of IMAGE variables or \n"
+" // ATOMIC COUNTERS and then returns with no other effect.\n"
+" memoryBarrier();\n"
+" // NOTE: nothing is said about buffer memory and shared memory,\n"
+" // so call memoryBarrierBuffer() and memoryBarrierShared() for safety\n"
+"\n"
+" // OpenGL.org: memoryBarrierBuffer() waits on the completion of \n"
+" // all memory accesses resulting from the use of BUFFER variables \n"
+" // and then returns with no other effect\n"
+" memoryBarrierBuffer();\n"
+"\n"
+" // OpenGL.org: memoryBarrierShared() waits on the completion of \n"
+" // all memory accesses resulting from the use of SHARED variables\n"
+" // and then returns with no other effect. \n"
+" memoryBarrierShared();\n"
+"\n"
+" // Call all memory barrier functions. They should have no effect\n"
+" // if everything is synchronized.\n"
+" \n"
+" // OpenGL.org: memoryBarrierImage() waits on the completion of all \n"
+" // memory accesses resulting from the use of IMAGE variables and then \n"
+" // returns with no other effect. \n"
+" memoryBarrierImage();\n"
+"\n"
+" // OpenGL.org: memoryBarrierAtomicCounter() waits on the completion of \n"
+" // all accesses resulting from the use of ATOMIC COUNTERS and then returns \n"
+" // with no other effect. \n"
+" memoryBarrierAtomicCounter();\n"
+"\n"
+" // groupMemoryBarrier waits on the completion of all memory accesses performed \n"
+" // by an invocation of a compute shader relative to the same access performed by \n"
+" // other invocations in the same work group and then returns with no other effect.\n"
+" groupMemoryBarrier();\n"
+"}\n"
+"\n"
+"// MSDN: AllMemoryBarrierWithGroupSync() blocks execution of all \n"
+"// threads in a group until all memory accesses have been completed \n"
+"// and all threads in the group have reached this call.\n"
+"void AllMemoryBarrierWithGroupSync()\n"
+"{\n"
+" AllMemoryBarrier();\n"
+" barrier();\n"
+"}\n"
+"\n"
+"#else\n"
+"\n"
+"void AllMemoryBarrier(){}\n"
+"void AllMemoryBarrierWithGroupSync(){}\n"
+"void DeviceMemoryBarrier(){}\n"
+"void DeviceMemoryBarrierWithGroupSync(){}\n"
+"void GroupMemoryBarrier(){}\n"
+"void GroupMemoryBarrierWithGroupSync(){}\n"
+"\n"
+"#endif\n"
+"\n"
+"\n"
+"// Type conversion functions\n"
+"\n"
+"vec4 _ExpandVector( float x ){ return vec4( x, x, x, x ); }\n"
+"vec4 _ExpandVector( vec2 f2 ){ return vec4( f2.x, f2.y, 0.0, 1.0 ); }\n"
+"vec4 _ExpandVector( vec3 f3 ){ return vec4( f3.x, f3.y, f3.z, 1.0 ); }\n"
+"vec4 _ExpandVector( vec4 f4 ){ return vec4( f4.x, f4.y, f4.z, f4.w ); }\n"
+"\n"
+"ivec4 _ExpandVector( int x ){ return ivec4( x, x, x, x ); }\n"
+"ivec4 _ExpandVector( ivec2 i2 ){ return ivec4( i2.x, i2.y, 0, 0 ); }\n"
+"ivec4 _ExpandVector( ivec3 i3 ){ return ivec4( i3.x, i3.y, i3.z, 0 ); }\n"
+"ivec4 _ExpandVector( ivec4 i4 ){ return ivec4( i4.x, i4.y, i4.z, i4.w ); }\n"
+"\n"
+"uvec4 _ExpandVector( uint x ){ return uvec4( x, x, x, x ); }\n"
+"uvec4 _ExpandVector( uvec2 u2 ){ return uvec4( u2.x, u2.y, 0u, 0u ); }\n"
+"uvec4 _ExpandVector( uvec3 u3 ){ return uvec4( u3.x, u3.y, u3.z, 0u ); }\n"
+"uvec4 _ExpandVector( uvec4 u4 ){ return uvec4( u4.x, u4.y, u4.z, u4.w ); }\n"
+"\n"
+"bvec4 _ExpandVector( bool x ){ return bvec4( x, x, x, x ); }\n"
+"bvec4 _ExpandVector( bvec2 b2 ){ return bvec4( b2.x, b2.y, false, false ); }\n"
+"bvec4 _ExpandVector( bvec3 b3 ){ return bvec4( b3.x, b3.y, b3.z, false ); }\n"
+"bvec4 _ExpandVector( bvec4 b4 ){ return bvec4( b4.x, b4.y, b4.z, b4.w ); }\n"
+"\n"
+"\n"
+"void _TypeConvertStore( out float Dst, in int Src ){ Dst = float( Src ); }\n"
+"void _TypeConvertStore( out float Dst, in uint Src ){ Dst = float( Src ); }\n"
+"void _TypeConvertStore( out float Dst, in float Src ){ Dst = float( Src ); }\n"
+"void _TypeConvertStore( out uint Dst, in int Src ){ Dst = uint( Src ); }\n"
+"void _TypeConvertStore( out uint Dst, in uint Src ){ Dst = uint( Src ); }\n"
+"void _TypeConvertStore( out uint Dst, in float Src ){ Dst = uint( Src ); }\n"
+"void _TypeConvertStore( out int Dst, in int Src ){ Dst = int( Src ); }\n"
+"void _TypeConvertStore( out int Dst, in uint Src ){ Dst = int( Src ); }\n"
+"void _TypeConvertStore( out int Dst, in float Src ){ Dst = int( Src ); }\n"
+"\n"
+"int _ToInt( int x ) { return int(x); }\n"
+"int _ToInt( uint x ) { return int(x); }\n"
+"int _ToInt( float x ){ return int(x); }\n"
+"int _ToInt( bool x ) { return x ? 1 : 0; }\n"
+"\n"
+"float _ToFloat( int x ) { return float(x); }\n"
+"float _ToFloat( uint x ) { return float(x); }\n"
+"float _ToFloat( float x ){ return float(x); }\n"
+"float _ToFloat( bool x ) { return x ? 1.0 : 0.0;}\n"
+"\n"
+"uint _ToUint( int x ) { return uint(x); }\n"
+"uint _ToUint( uint x ) { return uint(x); }\n"
+"uint _ToUint( float x ){ return uint(x); }\n"
+"uint _ToUint( bool x ) { return x ? 1u : 0u; }\n"
+"\n"
+"bool _ToBool( int x ) { return x != 0 ? true : false; }\n"
+"bool _ToBool( uint x ) { return x != 0u ? true : false; }\n"
+"bool _ToBool( float x ){ return x != 0.0 ? true : false; }\n"
+"bool _ToBool( bool x ) { return x; }\n"
+"\n"
+"#define _ToVec2(x,y) vec2(_ToFloat(x), _ToFloat(y))\n"
+"#define _ToVec3(x,y,z) vec3(_ToFloat(x), _ToFloat(y), _ToFloat(z))\n"
+"#define _ToVec4(x,y,z,w) vec4(_ToFloat(x), _ToFloat(y), _ToFloat(z), _ToFloat(w))\n"
+"\n"
+"#define _ToIvec2(x,y) ivec2(_ToInt(x), _ToInt(y))\n"
+"#define _ToIvec3(x,y,z) ivec3(_ToInt(x), _ToInt(y), _ToInt(z))\n"
+"#define _ToIvec4(x,y,z,w) ivec4(_ToInt(x), _ToInt(y), _ToInt(z), _ToInt(w))\n"
+"\n"
+"#define _ToUvec2(x,y) uvec2(_ToUint(x), _ToUint(y))\n"
+"#define _ToUvec3(x,y,z) uvec3(_ToUint(x), _ToUint(y), _ToUint(z))\n"
+"#define _ToUvec4(x,y,z,w) uvec4(_ToUint(x), _ToUint(y), _ToUint(z), _ToUint(w))\n"
+"\n"
+"#define _ToBvec2(x,y) bvec2(_ToBool(x), _ToBool(y))\n"
+"#define _ToBvec3(x,y,z) bvec3(_ToBool(x), _ToBool(y), _ToBool(z))\n"
+"#define _ToBvec4(x,y,z,w) bvec4(_ToBool(x), _ToBool(y), _ToBool(z), _ToBool(w))\n"
+"\n"
+"\n"
+"int _ToIvec( uint u1 ){ return _ToInt( u1 ); }\n"
+"ivec2 _ToIvec( uvec2 u2 ){ return _ToIvec2( u2.x, u2.y ); }\n"
+"ivec3 _ToIvec( uvec3 u3 ){ return _ToIvec3( u3.x, u3.y, u3.z ); }\n"
+"ivec4 _ToIvec( uvec4 u4 ){ return _ToIvec4( u4.x, u4.y, u4.z, u4.w ); }\n"
+"\n"
+"int _ToIvec( int i1 ){ return i1; }\n"
+"ivec2 _ToIvec( ivec2 i2 ){ return i2; }\n"
+"ivec3 _ToIvec( ivec3 i3 ){ return i3; }\n"
+"ivec4 _ToIvec( ivec4 i4 ){ return i4; }\n"
+"\n"
+"int _ToIvec( float f1 ){ return _ToInt( f1 ); }\n"
+"ivec2 _ToIvec( vec2 f2 ){ return _ToIvec2( f2.x, f2.y ); }\n"
+"ivec3 _ToIvec( vec3 f3 ){ return _ToIvec3( f3.x, f3.y, f3.z ); }\n"
+"ivec4 _ToIvec( vec4 f4 ){ return _ToIvec4( f4.x, f4.y, f4.z, f4.w ); }\n"
+"\n"
+"\n"
+"float _ToVec( uint u1 ){ return _ToFloat(u1); }\n"
+"vec2 _ToVec( uvec2 u2 ){ return _ToVec2( u2.x, u2.y ); }\n"
+"vec3 _ToVec( uvec3 u3 ){ return _ToVec3( u3.x, u3.y, u3.z ); }\n"
+"vec4 _ToVec( uvec4 u4 ){ return _ToVec4( u4.x, u4.y, u4.z, u4.w ); }\n"
+" \n"
+"float _ToVec( int i1 ){ return _ToFloat(i1); }\n"
+"vec2 _ToVec( ivec2 i2 ){ return _ToVec2( i2.x, i2.y ); }\n"
+"vec3 _ToVec( ivec3 i3 ){ return _ToVec3( i3.x, i3.y, i3.z ); }\n"
+"vec4 _ToVec( ivec4 i4 ){ return _ToVec4( i4.x, i4.y, i4.z, i4.w ); }\n"
+" \n"
+"float _ToVec( float f1 ){ return f1; }\n"
+"vec2 _ToVec( vec2 f2 ){ return f2; }\n"
+"vec3 _ToVec( vec3 f3 ){ return f3; }\n"
+"vec4 _ToVec( vec4 f4 ){ return f4; }\n"
+"\n"
+"\n"
+"uint _ToUvec( uint u1 ){ return u1; }\n"
+"uvec2 _ToUvec( uvec2 u2 ){ return u2; }\n"
+"uvec3 _ToUvec( uvec3 u3 ){ return u3; }\n"
+"uvec4 _ToUvec( uvec4 u4 ){ return u4; }\n"
+" \n"
+"uint _ToUvec( int i1 ){ return _ToUint( i1 ); }\n"
+"uvec2 _ToUvec( ivec2 i2 ){ return _ToUvec2( i2.x, i2.y ); }\n"
+"uvec3 _ToUvec( ivec3 i3 ){ return _ToUvec3( i3.x, i3.y, i3.z ); }\n"
+"uvec4 _ToUvec( ivec4 i4 ){ return _ToUvec4( i4.x, i4.y, i4.z, i4.w ); }\n"
+" \n"
+"uint _ToUvec( float f1 ){ return _ToUint( f1 ); }\n"
+"uvec2 _ToUvec( vec2 f2 ){ return _ToUvec2( f2.x, f2.y ); }\n"
+"uvec3 _ToUvec( vec3 f3 ){ return _ToUvec3( f3.x, f3.y, f3.z ); }\n"
+"uvec4 _ToUvec( vec4 f4 ){ return _ToUvec4( f4.x, f4.y, f4.z, f4.w ); }\n"
+"\n"
+"\n"
+"// TEXTURE FUNCTION STUB MACROS\n"
+"// https://www.opengl.org/wiki/Sampler_(GLSL)\n"
+"\n"
+"\n"
+"// Texture size queries\n"
+"// https://www.opengl.org/sdk/docs/man/html/textureSize.xhtml\n"
+"// textureSize returns the dimensions of level lod (if present) of the texture bound to sampler. \n"
+"// The components in the return value are filled in, in order, with the width, height and depth \n"
+"// of the texture. For the array forms, the last component of the return value is the number of \n"
+"// layers in the texture array.\n"
+"\n"
+"//#if !(defined(DESKTOP_GL) && __VERSION__ >= 430)\n"
+"# define textureQueryLevels(x) 0 // Only supported on 4.3+\n"
+"//#endif\n"
+"\n"
+"#define GetTex1DDimensions_1(Sampler, Width)\\\n"
+"{ \\\n"
+" _TypeConvertStore( Width, textureSize(Sampler, 0) );\\\n"
+"}\n"
+"\n"
+"#define GetTex1DDimensions_3(Sampler, MipLevel, Width, NumberOfMipLevels)\\\n"
+"{ \\\n"
+" _TypeConvertStore( Width, textureSize(Sampler, _ToInt(MipLevel)) ); \\\n"
+" _TypeConvertStore( NumberOfMipLevels, textureQueryLevels(Sampler) ); \\\n"
+"}\n"
+"\n"
+"#define GetTex1DArrDimensions_2(Sampler, Width, Elements)\\\n"
+"{ \\\n"
+" ivec2 i2Size = textureSize(Sampler, 0); \\\n"
+" _TypeConvertStore( Width, i2Size.x );\\\n"
+" _TypeConvertStore( Elements, i2Size.y );\\\n"
+"}\n"
+"\n"
+"#define GetTex1DArrDimensions_4(Sampler, MipLevel, Width, Elements, NumberOfMipLevels)\\\n"
+"{ \\\n"
+" ivec2 i2Size = textureSize(Sampler, _ToInt(MipLevel)); \\\n"
+" _TypeConvertStore( Width, i2Size.x ); \\\n"
+" _TypeConvertStore( Elements, i2Size.y ); \\\n"
+" _TypeConvertStore( NumberOfMipLevels, textureQueryLevels(Sampler) );\\\n"
+"}\n"
+"\n"
+"#define GetTex2DDimensions_2(Sampler, Width, Height)\\\n"
+"{ \\\n"
+" ivec2 i2Size = textureSize(Sampler, 0); \\\n"
+" _TypeConvertStore( Width, i2Size.x ); \\\n"
+" _TypeConvertStore( Height, i2Size.y ); \\\n"
+"}\n"
+"\n"
+"#define GetTex2DDimensions_4(Sampler, MipLevel, Width, Height, NumberOfMipLevels)\\\n"
+"{ \\\n"
+" ivec2 i2Size = textureSize(Sampler, _ToInt(MipLevel) ); \\\n"
+" _TypeConvertStore( Width, i2Size.x ); \\\n"
+" _TypeConvertStore( Height, i2Size.y ); \\\n"
+" _TypeConvertStore( NumberOfMipLevels, textureQueryLevels(Sampler) );\\\n"
+"}\n"
+"\n"
+"#define GetTex2DArrDimensions_3(Sampler, Width, Height, Elements)\\\n"
+"{ \\\n"
+" ivec3 i3Size = textureSize(Sampler, 0); \\\n"
+" _TypeConvertStore( Width, i3Size.x ); \\\n"
+" _TypeConvertStore( Height, i3Size.y ); \\\n"
+" _TypeConvertStore( Elements,i3Size.z ); \\\n"
+"}\n"
+"\n"
+"#define GetTex2DArrDimensions_5(Sampler, MipLevel, Width, Height, Elements, NumberOfMipLevels)\\\n"
+"{ \\\n"
+" ivec3 i3Size = textureSize(Sampler, _ToInt(MipLevel)); \\\n"
+" _TypeConvertStore( Width, i3Size.x ); \\\n"
+" _TypeConvertStore( Height, i3Size.y ); \\\n"
+" _TypeConvertStore( Elements, i3Size.z ); \\\n"
+" _TypeConvertStore( NumberOfMipLevels, textureQueryLevels(Sampler) );\\\n"
+"}\n"
+"\n"
+"#define GetTex3DDimensions_3(Sampler, Width, Height, Depth)\\\n"
+"{ \\\n"
+" ivec3 i3Size = textureSize(Sampler, 0); \\\n"
+" _TypeConvertStore( Width, i3Size.x ); \\\n"
+" _TypeConvertStore( Height, i3Size.y ); \\\n"
+" _TypeConvertStore( Depth, i3Size.z ); \\\n"
+"}\n"
+"\n"
+"#define GetTex3DDimensions_5(Sampler, MipLevel, Width, Height, Depth, NumberOfMipLevels)\\\n"
+"{ \\\n"
+" ivec3 i3Size = textureSize(Sampler, _ToInt(MipLevel)); \\\n"
+" _TypeConvertStore( Width, i3Size.x ); \\\n"
+" _TypeConvertStore( Height, i3Size.y ); \\\n"
+" _TypeConvertStore( Depth, i3Size.z ); \\\n"
+" _TypeConvertStore( NumberOfMipLevels, textureQueryLevels(Sampler) );\\\n"
+"}\n"
+"\n"
+"#define GetTex2DMSDimensions_3(Sampler, Width, Height, NumberOfSamples)\\\n"
+"{ \\\n"
+" ivec2 i2Size = textureSize(Sampler); \\\n"
+" _TypeConvertStore( Width, i2Size.x ); \\\n"
+" _TypeConvertStore( Height, i2Size.y ); \\\n"
+" _TypeConvertStore( NumberOfSamples, 0 );\\\n"
+"}\n"
+"\n"
+"#define GetTex2DMSArrDimensions_4(Sampler, Width, Height, Elements, NumberOfSamples)\\\n"
+"{ \\\n"
+" ivec3 i3Size = textureSize(Sampler); \\\n"
+" _TypeConvertStore( Width, i3Size.x );\\\n"
+" _TypeConvertStore( Height, i3Size.y );\\\n"
+" _TypeConvertStore( Elements, i3Size.z );\\\n"
+" _TypeConvertStore( NumberOfSamples, 0 );\\\n"
+"}\n"
+"\n"
+"\n"
+"// https://www.opengl.org/sdk/docs/man/html/imageSize.xhtml\n"
+"// imageSize returns the dimensions of the image bound to image. The components in the \n"
+"// return value are filled in, in order, with the width, height and depth of the image. \n"
+"// For the array forms, the last component of the return value is the number of layers \n"
+"// in the texture array.\n"
+"\n"
+"#define GetRWTex1DDimensions_1(Tex, Width)\\\n"
+"{ \\\n"
+" _TypeConvertStore( Width, imageSize(Tex) ); \\\n"
+"}\n"
+"\n"
+"#define GetRWTex1DArrDimensions_2(Tex, Width, Elements)\\\n"
+"{ \\\n"
+" ivec2 i2Size = imageSize(Tex); \\\n"
+" _TypeConvertStore( Width, i2Size.x ); \\\n"
+" _TypeConvertStore( Elements, i2Size.y ); \\\n"
+"}\n"
+"\n"
+"#define GetRWTex2DDimensions_2(Tex, Width, Height)\\\n"
+"{ \\\n"
+" ivec2 i2Size = imageSize(Tex); \\\n"
+" _TypeConvertStore( Width, i2Size.x ); \\\n"
+" _TypeConvertStore( Height, i2Size.y ); \\\n"
+"}\n"
+"\n"
+"#define GetRWTex2DArrDimensions_3(Tex, Width, Height, Elements)\\\n"
+"{ \\\n"
+" ivec3 i3Size = imageSize(Tex); \\\n"
+" _TypeConvertStore( Width, i3Size.x );\\\n"
+" _TypeConvertStore( Height, i3Size.y );\\\n"
+" _TypeConvertStore( Elements, i3Size.z );\\\n"
+"}\n"
+"\n"
+"#define GetRWTex3DDimensions_3(Tex, Width, Height, Depth)\\\n"
+"{ \\\n"
+" ivec3 i3Size = imageSize(Tex); \\\n"
+" _TypeConvertStore( Width, i3Size.x ); \\\n"
+" _TypeConvertStore( Height, i3Size.y ); \\\n"
+" _TypeConvertStore( Depth, i3Size.z ); \\\n"
+"}\n"
+"\n"
+"\n"
+"\n"
+"// Texture sampling operations\n"
+"\n"
+"\n"
+"// IMPORTANT NOTE ABOUT OFFSET\n"
+"// Offset parameter to all texture sampling functions must be a constant expression.\n"
+"// If it is not, the shader will be successfully compiled, HOWEVER the value of Offset \n"
+"// will silently be zero. \n"
+"//\n"
+"// A constant expression in GLSL is defined as follows:\n"
+"// * A literal value.\n"
+"// * A const-qualified variable with an explicit initializer (so not a function parameter).\n"
+"// * The result of the length() function of an array, but only if the array has an explicit size.\n"
+"// * The result of most operators, so long as all the operands are themselves constant expressions. \n"
+"// The operators not on this list are any assignment operators (+= and so forth), and the comma operator.\n"
+"// * The result of a constructor for a type, but only if all of the arguments to the constructor are \n"
+"// themselves constant expressions.\n"
+"// * The return value of any built-in function, but only if all of the arguments to the function are \n"
+"// themselves constant expressions. Opaque Types are never constant expressions. Note that the \n"
+"// functions dFdx, dFdy, and fwidth will return 0, when used in a context that requires a constant \n"
+"// expression (such as a const variable initializer).\n"
+"// \n"
+"// The list above does not include return value of a function, even when the value is compile-time expression.\n"
+"// As a result, we cannot use type conversion functions for Offset parameter.\n"
+"\n"
+"// In all texture sampling functions, the last component of Coords is used as Dsub and the array layer is specified \n"
+"// in the second to last component of Coords. (The second component of Coords is unused for 1D shadow lookups.)\n"
+"// For cube array textures, Dsub is specified as a separate parameter\n"
+"// mip\n"
+"#define SampleCmpLevel0Tex1D_3(Tex, Sampler, Coords, CompareValue) textureLod(Tex, _ToVec3((Coords).x, 0.0, CompareValue), 0.0)\n"
+"#define SampleCmpLevel0Tex1DArr_3(Tex, Sampler, Coords, CompareValue) textureLod(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue), 0.0)\n"
+"#define SampleCmpLevel0Tex2D_3(Tex, Sampler, Coords, CompareValue) textureLod(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue), 0.0)\n"
+"#define SampleCmpLevel0Tex2DArr_3(Tex, Sampler, Coords, CompareValue) 0.0 // No textureLod for sampler2DArrayShadow\n"
+"#define SampleCmpLevel0TexCube_3(Tex, Sampler, Coords, CompareValue) 0.0 // No textureLod for samplerCubeShadow\n"
+"#define SampleCmpLevel0TexCubeArr_3(Tex, Sampler, Coords, CompareValue) 0.0 // No textureLod for samplerCubeArrayShadow\n"
+"\n"
+"// mip\n"
+"#define SampleCmpLevel0Tex1D_4(Tex, Sampler, Coords, CompareValue, Offset) textureLodOffset(Tex, _ToVec3((Coords).x, 0.0, CompareValue), 0.0, int(Offset))\n"
+"#define SampleCmpLevel0Tex1DArr_4(Tex, Sampler, Coords, CompareValue, Offset) textureLodOffset(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue), 0.0, int(Offset))\n"
+"#define SampleCmpLevel0Tex2D_4(Tex, Sampler, Coords, CompareValue, Offset) textureLodOffset(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue), 0.0, ivec2((Offset).xy))\n"
+"#define SampleCmpLevel0Tex2DArr_4(Tex, Sampler, Coords, CompareValue, Offset) 0.0 // No textureLodOffset for sampler2DArrayShadow\n"
+"\n"
+"\n"
+"// https://www.opengl.org/sdk/docs/man/html/texture.xhtml - note: there are many mistakes on the page\n"
+"#ifdef FRAGMENT_SHADER\n"
+"\n"
+"# define Sample_2(Tex, Sampler, Coords) texture (Tex, _ToVec(Coords))\n"
+"# define Sample_3(Tex, Sampler, Coords, Offset) textureOffset(Tex, _ToVec(Coords), Offset)\n"
+"# define SampleBias_3(Tex, Sampler, Coords, Bias) texture (Tex, _ToVec(Coords), _ToFloat(Bias))\n"
+"# define SampleBias_4(Tex, Sampler, Coords, Bias, Offset) textureOffset(Tex, _ToVec(Coords), Offset, _ToFloat(Bias))\n"
+"\n"
+"# define SampleCmpTex1D_3(Tex, Sampler, Coords, CompareValue) texture(Tex, _ToVec3((Coords).x, 0.0, CompareValue))\n"
+"# define SampleCmpTex1DArr_3(Tex, Sampler, Coords, CompareValue) texture(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue))\n"
+"# define SampleCmpTex2D_3(Tex, Sampler, Coords, CompareValue) texture(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue))\n"
+"# define SampleCmpTex2DArr_3(Tex, Sampler, Coords, CompareValue) texture(Tex, _ToVec4((Coords).x, (Coords).y, (Coords).z, CompareValue))\n"
+"# define SampleCmpTexCube_3(Tex, Sampler, Coords, CompareValue) texture(Tex, _ToVec4((Coords).x, (Coords).y, (Coords).z, CompareValue))\n"
+"# define SampleCmpTexCubeArr_3(Tex, Sampler, Coords, CompareValue) texture(Tex, _ToVec4((Coords).x, (Coords).y, (Coords).z, (Coords).w), _ToFloat(CompareValue))\n"
+"\n"
+"# define SampleCmpTex1D_4(Tex, Sampler, Coords, CompareValue, Offset) textureOffset(Tex, _ToVec3((Coords).x, 0.0, CompareValue), int(Offset))\n"
+"# define SampleCmpTex1DArr_4(Tex, Sampler, Coords, CompareValue, Offset) textureOffset(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue), int(Offset))\n"
+"# define SampleCmpTex2D_4(Tex, Sampler, Coords, CompareValue, Offset) textureOffset(Tex, _ToVec3((Coords).x, (Coords).y, CompareValue), ivec2((Offset).xy))\n"
+"# define SampleCmpTex2DArr_4(Tex, Sampler, Coords, CompareValue, Offset) textureOffset(Tex, _ToVec4((Coords).x, (Coords).y, (Coords).z, CompareValue), ivec2((Offset).xy))\n"
+"\n"
+"#else\n"
+"\n"
+"// Derivatives are only available in fragment shader. GLSL compiler fails when it\n"
+"// encounters texture() or textureOffset() instructions in other types of shaders. So\n"
+"// to let the shader be compiled and to have something meaningful, replace such operations\n"
+"// with textureLod() and textureLodOffset()\n"
+"\n"
+"# define Sample_2(Tex, Sampler, Coords) textureLod (Tex, _ToVec(Coords), 0.0)\n"
+"# define Sample_3(Tex, Sampler, Coords, Offset) textureLodOffset(Tex, _ToVec(Coords), 0.0, Offset)\n"
+"# define SampleBias_3(Tex, Sampler, Coords, Bias) textureLod (Tex, _ToVec(Coords), 0.0 + _ToFloat(Bias))\n"
+"# define SampleBias_4(Tex, Sampler, Coords, Bias, Offset) textureLodOffset(Tex, _ToVec(Coords), 0.0 + _ToFloat(Bias), Offset)\n"
+"\n"
+"# define SampleCmpTex1D_3 SampleCmpLevel0Tex1D_3\n"
+"# define SampleCmpTex1DArr_3 SampleCmpLevel0Tex1DArr_3\n"
+"# define SampleCmpTex2D_3 SampleCmpLevel0Tex2D_3\n"
+"# define SampleCmpTex2DArr_3 SampleCmpLevel0Tex2DArr_3\n"
+"# define SampleCmpTexCube_3 SampleCmpLevel0TexCube_3\n"
+"# define SampleCmpTexCubeArr_3 SampleCmpLevel0TexCubeArr_3\n"
+" \n"
+"# define SampleCmpTex1D_4 SampleCmpLevel0Tex1D_4\n"
+"# define SampleCmpTex1DArr_4 SampleCmpLevel0Tex1DArr_4\n"
+"# define SampleCmpTex2D_4 SampleCmpLevel0Tex2D_4\n"
+"# define SampleCmpTex2DArr_4 SampleCmpLevel0Tex2DArr_4\n"
+"\n"
+"#endif\n"
+"\n"
+"// https://www.opengl.org/sdk/docs/man/html/textureLod.xhtml\n"
+"#define SampleLevel_3(Tex, Sampler, Coords, Level) textureLod (Tex, _ToVec(Coords), _ToFloat(Level))\n"
+"#define SampleLevel_4(Tex, Sampler, Coords, Level, Offset) textureLodOffset(Tex, _ToVec(Coords), _ToFloat(Level), Offset)\n"
+"\n"
+"// https://www.opengl.org/sdk/docs/man/html/textureGrad.xhtml\n"
+"#define SampleGrad_4(Tex, Sampler, Coords, DDX, DDY) textureGrad (Tex, _ToVec(Coords), _ToVec(DDX), _ToVec(DDY))\n"
+"#define SampleGrad_5(Tex, Sampler, Coords, DDX, DDY, Offset) textureGradOffset(Tex, _ToVec(Coords), _ToVec(DDX), _ToVec(DDY), Offset)\n"
+"\n"
+"\n"
+"// texelFetch performs a lookup of a single texel from texture coordinate P in the texture \n"
+"// bound to sampler. The array layer is specified in the last component of P for array forms. \n"
+"// The lod parameter (if present) specifies the level-of-detail from which the texel will be fetched. \n"
+"// The sample specifies which sample within the texel will be returned when reading from a multi-sample texure.\n"
+"\n"
+"#define LoadTex1D_1(Tex, Location) texelFetch (Tex, _ToInt((Location).x), _ToInt((Location).y))\n"
+"#define LoadTex1D_2(Tex, Location, Offset)texelFetchOffset(Tex, _ToInt((Location).x), _ToInt((Location).y), int(Offset))\n"
+"#define LoadTex1DArr_1(Tex, Location) texelFetch (Tex, _ToIvec( (Location).xy), _ToInt((Location).z) )\n"
+"#define LoadTex1DArr_2(Tex, Location, Offset)texelFetchOffset(Tex, _ToIvec( (Location).xy), _ToInt((Location).z), int(Offset))\n"
+"#define LoadTex2D_1(Tex, Location) texelFetch (Tex, _ToIvec( (Location).xy), _ToInt((Location).z))\n"
+"#define LoadTex2D_2(Tex, Location, Offset)texelFetchOffset(Tex, _ToIvec( (Location).xy), _ToInt((Location).z), ivec2( (Offset).xy) )\n"
+"#define LoadTex2DArr_1(Tex, Location) texelFetch (Tex, _ToIvec( (Location).xyz), _ToInt((Location).w) )\n"
+"#define LoadTex2DArr_2(Tex, Location, Offset)texelFetchOffset(Tex, _ToIvec( (Location).xyz), _ToInt((Location).w), ivec2( (Offset).xy))\n"
+"#define LoadTex3D_1(Tex, Location) texelFetch (Tex, _ToIvec( (Location).xyz), _ToInt((Location).w))\n"
+"#define LoadTex3D_2(Tex, Location, Offset)texelFetchOffset(Tex, _ToIvec( (Location).xyz), _ToInt((Location).w), ivec3( (Offset).xyz))\n"
+"#define LoadTex2DMS_2(Tex, Location, Sample) texelFetch(Tex, _ToIvec( (Location).xy), _ToInt(Sample))\n"
+"#define LoadTex2DMS_3(Tex, Location, Sample, Offset)texelFetch(Tex, _ToIvec2( (Location).x + (Offset).x, (Location).y + (Offset).y), int(Sample) ) // No texelFetchOffset for texture2DMS\n"
+"#define LoadTex2DMSArr_2(Tex, Location, Sample) texelFetch(Tex, _ToIvec( (Location).xyz), _ToInt(Sample))\n"
+"#define LoadTex2DMSArr_3(Tex, Location, Sample, Offset)texelFetch(Tex, _ToIvec3( (Location).x + (Offset).x, (Location).y + (Offset).y, (Location).z), int(Sample)) // No texelFetchOffset for texture2DMSArray\n"
+"\n"
+"//https://www.opengl.org/sdk/docs/man/html/imageLoad.xhtml\n"
+"#define LoadRWTex1D_1(Tex, Location) imageLoad(Tex, _ToIvec((Location).x) )\n"
+"#define LoadRWTex1DArr_1(Tex, Location) imageLoad(Tex, _ToIvec((Location).xy) )\n"
+"#define LoadRWTex2D_1(Tex, Location) imageLoad(Tex, _ToIvec((Location).xy) )\n"
+"#define LoadRWTex2DArr_1(Tex, Location) imageLoad(Tex, _ToIvec((Location).xyz) )\n"
+"#define LoadRWTex3D_1(Tex, Location) imageLoad(Tex, _ToIvec((Location).xyz) )\n"
+"\n"
+"\n"
+"#define Gather_2(Tex, Sampler, Location) textureGather (Tex, _ToVec(Location))\n"
+"#define Gather_3(Tex, Sampler, Location, Offset)textureGatherOffset(Tex, _ToVec(Location), Offset)\n"
+"\n"
+"#define GatherCmp_3(Tex, Sampler, Location, CompareVal) textureGather (Tex, _ToVec(Location), _ToFloat(CompareVal))\n"
+"#define GatherCmp_4(Tex, Sampler, Location, CompareVal, Offset)textureGatherOffset(Tex, _ToVec(Location), _ToFloat(CompareVal), Offset)\n"
+"\n"
+"// Atomic operations\n"
+"#define InterlockedAddSharedVar_2(dest, value) atomicAdd(dest, value)\n"
+"#define InterlockedAddSharedVar_3(dest, value, orig_val) orig_val = atomicAdd(dest, value)\n"
+"#define InterlockedAddImage_2(img, coords, value) imageAtomicAdd(img, _ToIvec(coords), value)\n"
+"#define InterlockedAddImage_3(img, coords, value, orig_val)orig_val = imageAtomicAdd(img, _ToIvec(coords), value)\n"
+"\n"
+"#define InterlockedAndSharedVar_2(dest, value) atomicAnd(dest, value)\n"
+"#define InterlockedAndSharedVar_3(dest, value, orig_val) orig_val = atomicAnd(dest, value)\n"
+"#define InterlockedAndImage_2(img, coords, value) imageAtomicAnd(img, _ToIvec(coords), value)\n"
+"#define InterlockedAndImage_3(img, coords, value, orig_val)orig_val = imageAtomicAnd(img, _ToIvec(coords), value)\n"
+"\n"
+"#define InterlockedMaxSharedVar_2(dest, value) atomicMax(dest, value)\n"
+"#define InterlockedMaxSharedVar_3(dest, value, orig_val) orig_val = atomicMax(dest, value)\n"
+"#define InterlockedMaxImage_2(img, coords, value) imageAtomicMax(img, _ToIvec(coords), value)\n"
+"#define InterlockedMaxImage_3(img, coords, value, orig_val)orig_val = imageAtomicMax(img, _ToIvec(coords), value)\n"
+"\n"
+"#define InterlockedMinSharedVar_2(dest, value) atomicMin(dest, value)\n"
+"#define InterlockedMinSharedVar_3(dest, value, orig_val) orig_val = atomicMin(dest, value)\n"
+"#define InterlockedMinImage_2(img, coords, value) imageAtomicMin(img, _ToIvec(coords), value)\n"
+"#define InterlockedMinImage_3(img, coords, value, orig_val)orig_val = imageAtomicMin(img, _ToIvec(coords), value)\n"
+"\n"
+"#define InterlockedOrSharedVar_2(dest, value) atomicOr(dest, value)\n"
+"#define InterlockedOrSharedVar_3(dest, value, orig_val) orig_val = atomicOr(dest, value)\n"
+"#define InterlockedOrImage_2(img, coords, value) imageAtomicOr(img, _ToIvec(coords), value)\n"
+"#define InterlockedOrImage_3(img, coords, value, orig_val)orig_val = imageAtomicOr(img, _ToIvec(coords), value)\n"
+"\n"
+"#define InterlockedXorSharedVar_2(dest, value) atomicXor(dest, value)\n"
+"#define InterlockedXorSharedVar_3(dest, value, orig_val) orig_val = atomicXor(dest, value)\n"
+"#define InterlockedXorImage_2(img, coords, value) imageAtomicXor(img, _ToIvec(coords), value)\n"
+"#define InterlockedXorImage_3(img, coords, value, orig_val)orig_val = imageAtomicXor(img, _ToIvec(coords), value)\n"
+"\n"
+"// There is actually no InterlockedExchange() with 2 arguments\n"
+"#define InterlockedExchangeSharedVar_2(dest, value) atomicExchange(dest, value)\n"
+"#define InterlockedExchangeSharedVar_3(dest, value, orig_val) orig_val = atomicExchange(dest, value)\n"
+"#define InterlockedExchangeImage_2(img, coords, value) imageAtomicExchange(img, _ToIvec(coords), value)\n"
+"#define InterlockedExchangeImage_3(img, coords, value, orig_val)orig_val = imageAtomicExchange(img, _ToIvec(coords), value)\n"
+"\n"
+"//uint imageAtomicCompSwap( image img, IVec P, nint compare, nint data);\n"
+"//void InterlockedCompareExchange( in R dest, in T compare_value, in T value, out T original_value);\n"
+"#define InterlockedCompareExchangeSharedVar_4(dest, cmp_val, value, orig_val) orig_val = atomicCompSwap(dest, cmp_val, value)\n"
+"#define InterlockedCompareExchangeImage_4(img, coords, cmp_val, value, orig_val) orig_val = imageAtomicCompSwap(img, _ToIvec(coords), cmp_val, value)\n"
+"\n"
+"#define InterlockedCompareStoreSharedVar_3(dest, cmp_val, value) atomicCompSwap(dest, cmp_val, value)\n"
+"#define InterlockedCompareStoreImage_3(img, coords, cmp_val, value)imageAtomicCompSwap(img, _ToIvec(coords), cmp_val, value)\n"
+"\n"
+"\n"
+"// Swizzling macros\n"
+"#define _SWIZZLE0\n"
+"#define _SWIZZLE1 .x\n"
+"#define _SWIZZLE2 .xy\n"
+"#define _SWIZZLE3 .xyz\n"
+"#define _SWIZZLE4 .xyzw\n"
+"\n"
+"// Helper functions\n"
+"\n"
+"float2 NormalizedDeviceXYToTexUV( float2 f2ProjSpaceXY )\n"
+"{\n"
+" return float2(0.5,0.5) + float2(0.5,0.5) * f2ProjSpaceXY.xy;\n"
+"}\n"
+"\n"
+"float NormalizedDeviceZToDepth(float fNDC_Z)\n"
+"{\n"
+" return fNDC_Z * 0.5 + 0.5; // [-1, +1] -> [0, 1]\n"
+"}\n"
+"\n"
+"float DepthToNormalizedDeviceZ(float fDepth)\n"
+"{\n"
+" return fDepth * 2.0 - 1.0; // [0, 1] -> [-1, +1]\n"
+"}\n"
+"\n"
+"#define F3NDC_XYZ_TO_UVD_SCALE float3(0.5, 0.5, 0.5)\n"
+"\n"
+"#define NDC_MIN_Z -1.0 // Minimal z in the normalized device space\n"
+"\n"
+"#define MATRIX_ELEMENT(mat, row, col) mat[col][row]\n"
+"\n"
+"#endif // _GLSL_DEFINITIONS_\n"
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLStubs.h b/Graphics/GraphicsEngineOpenGL/include/GLStubs.h
new file mode 100644
index 00000000..f5308af8
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/GLStubs.h
@@ -0,0 +1,1051 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+// Define unsupported formats for OpenGL ES
+#ifndef GL_RGBA16
+# define GL_RGBA16 0x805B
+#endif
+
+#ifndef GL_RGBA16_SNORM
+# define GL_RGBA16_SNORM 0x8F9B
+#endif
+
+#ifndef GL_RG16
+# define GL_RG16 0x822C
+#endif
+
+#ifndef GL_RG16_SNORM
+# define GL_RG16_SNORM 0x8F99
+#endif
+
+#ifndef GL_R16
+# define GL_R16 0x822A
+#endif
+
+#ifndef GL_R16_SNORM
+# define GL_R16_SNORM 0x8F98
+#endif
+
+#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
+# define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#endif
+
+#ifndef GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
+# define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
+#endif
+
+#ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
+# define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#endif
+
+#ifndef GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
+# define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#endif
+
+#ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
+# define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#endif
+
+#ifndef GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
+# define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+#endif
+
+#ifndef GL_COMPRESSED_RED_RGTC1
+# define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#endif
+
+#ifndef GL_COMPRESSED_SIGNED_RED_RGTC1
+# define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#endif
+
+#ifndef GL_COMPRESSED_RG_RGTC2
+# define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#endif
+
+#ifndef GL_COMPRESSED_SIGNED_RG_RGTC2
+# define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#endif
+
+#ifndef GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT
+# define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+#endif
+
+#ifndef GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT
+# define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#endif
+
+#ifndef GL_COMPRESSED_RGBA_BPTC_UNORM
+# define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#endif
+
+#ifndef GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM
+# define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#endif
+
+#ifndef GL_UNSIGNED_SHORT_5_6_5_REV
+# define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#endif
+
+#ifndef GL_UNSIGNED_INT_10_10_10_2
+# define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#endif
+
+#ifndef GL_UNSIGNED_SHORT_5_6_5_REV
+# define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#endif
+
+#ifndef GL_UNSIGNED_SHORT_1_5_5_5_REV
+# define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#endif
+
+// Define unsupported shaders
+#ifndef GL_GEOMETRY_SHADER
+# define GL_GEOMETRY_SHADER 0x8DD9
+#endif
+
+#ifndef GL_TESS_CONTROL_SHADER
+# define GL_TESS_CONTROL_SHADER 0x8E88
+#endif
+
+#ifndef GL_TESS_EVALUATION_SHADER
+# define GL_TESS_EVALUATION_SHADER 0x8E87
+#endif
+
+// Define unsupported texture filtering modes
+#ifndef GL_CLAMP_TO_BORDER
+# define GL_CLAMP_TO_BORDER 0
+#endif
+
+#ifndef GL_MIRROR_CLAMP_TO_EDGE
+# define GL_MIRROR_CLAMP_TO_EDGE 0
+#endif
+
+// Define unsupported bind points
+#ifndef GL_DRAW_INDIRECT_BUFFER
+# define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#endif
+
+#ifndef GL_DISPATCH_INDIRECT_BUFFER
+# define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
+#endif
+
+#ifndef GL_TEXTURE_1D_ARRAY
+# define GL_TEXTURE_1D_ARRAY 0x8C18
+#endif
+
+#ifndef GL_TEXTURE_BINDING_1D_ARRAY
+# define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#endif
+
+#ifndef GL_TEXTURE_1D
+# define GL_TEXTURE_1D 0x0DE0
+#endif
+
+#ifndef GL_TEXTURE_BINDING_1D
+# define GL_TEXTURE_BINDING_1D 0x8068
+#endif
+
+#ifndef GL_TEXTURE_2D_MULTISAMPLE
+# define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#endif
+
+#ifndef GL_TEXTURE_BINDING_2D_MULTISAMPLE
+# define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#endif
+
+#ifndef GL_TEXTURE_2D_MULTISAMPLE_ARRAY
+# define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#endif
+
+#ifndef GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY
+# define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#endif
+
+#ifndef GL_TEXTURE_BUFFER
+# define GL_TEXTURE_BUFFER 0x8C2A
+#endif
+
+// Define unsupported pipeline bind flags
+#ifndef GL_VERTEX_SHADER_BIT
+# define GL_VERTEX_SHADER_BIT 0x00000001
+#endif
+
+#ifndef GL_FRAGMENT_SHADER_BIT
+# define GL_FRAGMENT_SHADER_BIT 0x00000002
+#endif
+
+#ifndef GL_GEOMETRY_SHADER_BIT
+# define GL_GEOMETRY_SHADER_BIT 0x00000004
+#endif
+
+#ifndef GL_TESS_CONTROL_SHADER_BIT
+# define GL_TESS_CONTROL_SHADER_BIT 0x00000008
+#endif
+
+#ifndef GL_TESS_EVALUATION_SHADER_BIT
+# define GL_TESS_EVALUATION_SHADER_BIT 0x00000010
+#endif
+
+#ifndef GL_COMPUTE_SHADER_BIT
+# define GL_COMPUTE_SHADER_BIT 0x00000020
+#endif
+
+// Define unsupported sampler attributes
+#ifndef GL_TEXTURE_LOD_BIAS
+# define GL_TEXTURE_LOD_BIAS 0
+#endif
+
+#ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT
+# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0
+#endif
+
+#ifndef GL_TEXTURE_BORDER_COLOR
+# define GL_TEXTURE_BORDER_COLOR 0
+#endif
+
+// Other unsupported attributes
+#ifndef GL_PROGRAM_SEPARABLE
+# define GL_PROGRAM_SEPARABLE 0x8258
+#endif
+
+// Define unsupported uniform data types
+#ifndef GL_SAMPLER_1D
+ #define GL_SAMPLER_1D 0x8B5D
+#endif
+
+#ifndef GL_SAMPLER_1D_SHADOW
+ #define GL_SAMPLER_1D_SHADOW 0x8B61
+#endif
+
+#ifndef GL_SAMPLER_1D_ARRAY
+ #define GL_SAMPLER_1D_ARRAY 0x8DC0
+#endif
+
+#ifndef GL_SAMPLER_1D_ARRAY_SHADOW
+ #define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#endif
+
+#ifndef GL_INT_SAMPLER_1D
+ #define GL_INT_SAMPLER_1D 0x8DC9
+#endif
+
+#ifndef GL_INT_SAMPLER_1D_ARRAY
+ #define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#endif
+
+#ifndef GL_UNSIGNED_INT_SAMPLER_1D
+ #define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#endif
+
+#ifndef GL_UNSIGNED_INT_SAMPLER_1D_ARRAY
+ #define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#endif
+
+#ifndef GL_SAMPLER_CUBE_MAP_ARRAY
+ #define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#endif
+
+#ifndef GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW
+ #define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#endif
+
+#ifndef GL_INT_SAMPLER_CUBE_MAP_ARRAY
+ #define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#endif
+
+#ifndef GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY
+ #define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+#endif
+
+#ifndef GL_SAMPLER_BUFFER
+ #define GL_SAMPLER_BUFFER 0x8DC2
+#endif
+
+#ifndef GL_INT_SAMPLER_BUFFER
+ #define GL_INT_SAMPLER_BUFFER 0x8DD0
+#endif
+
+#ifndef GL_UNSIGNED_INT_SAMPLER_BUFFER
+ #define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#endif
+
+#ifndef GL_SAMPLER_2D_MULTISAMPLE
+ #define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#endif
+
+#ifndef GL_INT_SAMPLER_2D_MULTISAMPLE
+ #define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#endif
+
+#ifndef GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE
+ #define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#endif
+
+#ifndef GL_SAMPLER_2D_MULTISAMPLE_ARRAY
+ #define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#endif
+
+#ifndef GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY
+ #define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#endif
+
+#ifndef GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY
+ #define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#endif
+
+
+#ifndef GL_IMAGE_1D
+ #define GL_IMAGE_1D 0x904C
+#endif
+
+#ifndef GL_IMAGE_2D
+ #define GL_IMAGE_2D 0x904D
+#endif
+
+#ifndef GL_IMAGE_3D
+ #define GL_IMAGE_3D 0x904E
+#endif
+
+#ifndef GL_IMAGE_2D_RECT
+ #define GL_IMAGE_2D_RECT 0x904F
+#endif
+
+#ifndef GL_IMAGE_CUBE
+ #define GL_IMAGE_CUBE 0x9050
+#endif
+
+#ifndef GL_IMAGE_BUFFER
+ #define GL_IMAGE_BUFFER 0x9051
+#endif
+
+#ifndef GL_IMAGE_1D_ARRAY
+ #define GL_IMAGE_1D_ARRAY 0x9052
+#endif
+
+#ifndef GL_IMAGE_2D_ARRAY
+ #define GL_IMAGE_2D_ARRAY 0x9053
+#endif
+
+#ifndef GL_IMAGE_CUBE_MAP_ARRAY
+ #define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#endif
+
+#ifndef GL_IMAGE_2D_MULTISAMPLE
+ #define GL_IMAGE_2D_MULTISAMPLE 0x9055
+#endif
+
+#ifndef GL_IMAGE_2D_MULTISAMPLE_ARRAY
+ #define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+#endif
+
+#ifndef GL_INT_IMAGE_1D
+ #define GL_INT_IMAGE_1D 0x9057
+#endif
+
+#ifndef GL_INT_IMAGE_2D
+ #define GL_INT_IMAGE_2D 0x9058
+#endif
+
+#ifndef GL_INT_IMAGE_3D
+ #define GL_INT_IMAGE_3D 0x9059
+#endif
+
+#ifndef GL_INT_IMAGE_2D_RECT
+ #define GL_INT_IMAGE_2D_RECT 0x905A
+#endif
+
+#ifndef GL_INT_IMAGE_CUBE
+ #define GL_INT_IMAGE_CUBE 0x905B
+#endif
+
+#ifndef GL_INT_IMAGE_BUFFER
+ #define GL_INT_IMAGE_BUFFER 0x905C
+#endif
+
+#ifndef GL_INT_IMAGE_1D_ARRAY
+ #define GL_INT_IMAGE_1D_ARRAY 0x905D
+#endif
+
+#ifndef GL_INT_IMAGE_2D_ARRAY
+ #define GL_INT_IMAGE_2D_ARRAY 0x905E
+#endif
+
+#ifndef GL_INT_IMAGE_CUBE_MAP_ARRAY
+ #define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#endif
+
+#ifndef GL_INT_IMAGE_2D_MULTISAMPLE
+ #define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+#endif
+
+#ifndef GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY
+ #define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+#endif
+
+#ifndef GL_UNSIGNED_INT_IMAGE_1D
+ #define GL_UNSIGNED_INT_IMAGE_1D 0x9062
+#endif
+
+#ifndef GL_UNSIGNED_INT_IMAGE_2D
+ #define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#endif
+
+#ifndef GL_UNSIGNED_INT_IMAGE_3D
+ #define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#endif
+
+#ifndef GL_UNSIGNED_INT_IMAGE_2D_RECT
+ #define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+#endif
+
+#ifndef GL_UNSIGNED_INT_IMAGE_CUBE
+ #define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#endif
+
+#ifndef GL_UNSIGNED_INT_IMAGE_BUFFER
+ #define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#endif
+
+#ifndef GL_UNSIGNED_INT_IMAGE_1D_ARRAY
+ #define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+#endif
+
+#ifndef GL_UNSIGNED_INT_IMAGE_2D_ARRAY
+ #define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#endif
+
+#ifndef GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY
+ #define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#endif
+
+#ifndef GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE
+ #define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+#endif
+
+#ifndef GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY
+ #define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
+#endif
+
+
+// Compute shader stubs
+#ifndef GL_READ_ONLY
+# define GL_READ_ONLY 0x88B8
+#endif
+
+#ifndef GL_WRITE_ONLY
+# define GL_WRITE_ONLY 0x88B9
+#endif
+
+#ifndef GL_READ_WRITE
+# define GL_READ_WRITE 0x88BA
+#endif
+
+#ifndef GL_COMPUTE_SHADER
+# define GL_COMPUTE_SHADER 0x91B9
+#endif
+
+#ifndef glBindImageTexture
+ #define LOAD_GL_BIND_IMAGE_TEXTURE
+ typedef void (* PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+ extern PFNGLBINDIMAGETEXTUREPROC glBindImageTexture;
+#endif
+
+#ifndef glDispatchCompute
+ #define LOAD_GL_DISPATCH_COMPUTE
+ typedef void (* PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+ extern PFNGLDISPATCHCOMPUTEPROC glDispatchCompute;
+#endif
+
+#ifndef glMemoryBarrier
+ #define LOAD_GL_MEMORY_BARRIER
+ typedef void (* PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+ extern PFNGLMEMORYBARRIERPROC glMemoryBarrier;
+#endif
+
+#ifndef GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT
+# define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#endif
+#ifndef GL_ELEMENT_ARRAY_BARRIER_BIT
+# define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#endif
+#ifndef GL_UNIFORM_BARRIER_BIT
+# define GL_UNIFORM_BARRIER_BIT 0x00000004
+#endif
+#ifndef GL_TEXTURE_FETCH_BARRIER_BIT
+# define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#endif
+#ifndef GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
+# define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#endif
+#ifndef GL_COMMAND_BARRIER_BIT
+# define GL_COMMAND_BARRIER_BIT 0x00000040
+#endif
+#ifndef GL_PIXEL_BUFFER_BARRIER_BIT
+# define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#endif
+#ifndef GL_TEXTURE_UPDATE_BARRIER_BIT
+# define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#endif
+#ifndef GL_BUFFER_UPDATE_BARRIER_BIT
+# define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#endif
+#ifndef GL_FRAMEBUFFER_BARRIER_BIT
+# define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#endif
+#ifndef GL_TRANSFORM_FEEDBACK_BARRIER_BIT
+# define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#endif
+#ifndef GL_ATOMIC_COUNTER_BARRIER_BIT
+# define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#endif
+#ifndef GL_SHADER_STORAGE_BARRIER_BIT
+# define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
+#endif
+#ifndef GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT
+# define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000
+#endif
+#ifndef GL_QUERY_BUFFER_BARRIER_BIT
+# define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000
+#endif
+#ifndef GL_ALL_BARRIER_BITS
+# define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#endif
+
+
+
+//------------------------ Program interface query ------------------------
+#ifndef GL_UNIFORM
+# define GL_UNIFORM 0x92E1
+#endif
+
+#ifndef GL_UNIFORM_BLOCK
+# define GL_UNIFORM_BLOCK 0x92E2
+#endif
+
+#ifndef GL_PROGRAM_INPUT
+# define GL_PROGRAM_INPUT 0x92E3
+#endif
+
+#ifndef GL_PROGRAM_OUTPUT
+# define GL_PROGRAM_OUTPUT 0x92E4
+#endif
+
+#ifndef GL_BUFFER_VARIABLE
+# define GL_BUFFER_VARIABLE 0x92E5
+#endif
+
+#ifndef GL_SHADER_STORAGE_BLOCK
+# define GL_SHADER_STORAGE_BLOCK 0x92E6
+#endif
+
+#ifndef GL_IS_PER_PATCH
+# define GL_IS_PER_PATCH 0x92E7
+#endif
+
+#ifndef GL_VERTEX_SUBROUTINE
+# define GL_VERTEX_SUBROUTINE 0x92E8
+#endif
+
+#ifndef GL_TESS_CONTROL_SUBROUTINE
+# define GL_TESS_CONTROL_SUBROUTINE 0x92E9
+#endif
+
+#ifndef GL_TESS_EVALUATION_SUBROUTINE
+# define GL_TESS_EVALUATION_SUBROUTINE 0x92EA
+#endif
+
+#ifndef GL_GEOMETRY_SUBROUTINE
+# define GL_GEOMETRY_SUBROUTINE 0x92EB
+#endif
+
+#ifndef GL_FRAGMENT_SUBROUTINE
+# define GL_FRAGMENT_SUBROUTINE 0x92EC
+#endif
+
+#ifndef GL_COMPUTE_SUBROUTINE
+# define GL_COMPUTE_SUBROUTINE 0x92ED
+#endif
+
+#ifndef GL_VERTEX_SUBROUTINE_UNIFORM
+# define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE
+#endif
+
+#ifndef GL_TESS_CONTROL_SUBROUTINE_UNIFORM
+# define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF
+#endif
+
+#ifndef GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
+# define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0
+#endif
+
+#ifndef GL_GEOMETRY_SUBROUTINE_UNIFORM
+# define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1
+#endif
+
+#ifndef GL_FRAGMENT_SUBROUTINE_UNIFORM
+# define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2
+#endif
+
+#ifndef GL_COMPUTE_SUBROUTINE_UNIFORM
+# define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3
+#endif
+
+#ifndef GL_TRANSFORM_FEEDBACK_VARYING
+# define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4
+#endif
+
+#ifndef GL_ACTIVE_RESOURCES
+# define GL_ACTIVE_RESOURCES 0x92F5
+#endif
+
+#ifndef GL_MAX_NAME_LENGTH
+# define GL_MAX_NAME_LENGTH 0x92F6
+#endif
+
+#ifndef GL_MAX_NUM_ACTIVE_VARIABLES
+# define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#endif
+
+#ifndef GL_MAX_NUM_COMPATIBLE_SUBROUTINES
+# define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
+#endif
+
+#ifndef GL_NAME_LENGTH
+# define GL_NAME_LENGTH 0x92F9
+#endif
+
+#ifndef GL_TYPE
+# define GL_TYPE 0x92FA
+#endif
+
+#ifndef GL_ARRAY_SIZE
+# define GL_ARRAY_SIZE 0x92FB
+#endif
+
+#ifndef GL_OFFSET
+# define GL_OFFSET 0x92FC
+#endif
+
+#ifndef GL_BLOCK_INDEX
+# define GL_BLOCK_INDEX 0x92FD
+#endif
+
+#ifndef GL_ARRAY_STRIDE
+# define GL_ARRAY_STRIDE 0x92FE
+#endif
+
+#ifndef GL_MATRIX_STRIDE
+# define GL_MATRIX_STRIDE 0x92FF
+#endif
+
+#ifndef GL_IS_ROW_MAJOR
+# define GL_IS_ROW_MAJOR 0x9300
+#endif
+
+#ifndef GL_ATOMIC_COUNTER_BUFFER_INDEX
+# define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#endif
+
+#ifndef GL_BUFFER_BINDING
+# define GL_BUFFER_BINDING 0x9302
+#endif
+
+#ifndef GL_BUFFER_DATA_SIZE
+# define GL_BUFFER_DATA_SIZE 0x9303
+#endif
+
+#ifndef GL_NUM_ACTIVE_VARIABLES
+# define GL_NUM_ACTIVE_VARIABLES 0x9304
+#endif
+
+#ifndef GL_ACTIVE_VARIABLES
+# define GL_ACTIVE_VARIABLES 0x9305
+#endif
+
+#ifndef GL_REFERENCED_BY_VERTEX_SHADER
+# define GL_REFERENCED_BY_VERTEX_SHADER 0x9306
+#endif
+
+#ifndef GL_REFERENCED_BY_TESS_CONTROL_SHADER
+# define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#endif
+
+#ifndef GL_REFERENCED_BY_TESS_EVALUATION_SHADER
+# define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#endif
+
+#ifndef GL_REFERENCED_BY_GEOMETRY_SHADER
+# define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309
+#endif
+
+#ifndef GL_REFERENCED_BY_FRAGMENT_SHADER
+# define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A
+#endif
+
+#ifndef GL_REFERENCED_BY_COMPUTE_SHADER
+# define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B
+#endif
+
+#ifndef GL_TOP_LEVEL_ARRAY_SIZE
+# define GL_TOP_LEVEL_ARRAY_SIZE 0x930C
+#endif
+
+#ifndef GL_TOP_LEVEL_ARRAY_STRIDE
+# define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D
+#endif
+
+#ifndef GL_LOCATION
+# define GL_LOCATION 0x930E
+#endif
+
+#ifndef GL_LOCATION_INDEX
+# define GL_LOCATION_INDEX 0x930F
+#endif
+
+
+
+// --------------------- Shader storage buffer -----------------------
+
+#ifndef GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES
+# define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#endif
+
+#ifndef GL_SHADER_STORAGE_BUFFER
+# define GL_SHADER_STORAGE_BUFFER 0x90D2
+#endif
+
+#ifndef GL_SHADER_STORAGE_BUFFER_BINDING
+# define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3
+#endif
+
+#ifndef GL_SHADER_STORAGE_BUFFER_START
+# define GL_SHADER_STORAGE_BUFFER_START 0x90D4
+#endif
+
+#ifndef GL_SHADER_STORAGE_BUFFER_SIZE
+# define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5
+#endif
+
+#ifndef GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS
+# define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#endif
+
+#ifndef GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS
+# define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#endif
+
+#ifndef GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS
+# define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#endif
+
+#ifndef GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS
+# define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#endif
+
+#ifndef GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS
+# define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#endif
+
+#ifndef GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS
+# define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#endif
+
+#ifndef GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS
+# define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#endif
+
+#ifndef GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS
+# define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#endif
+
+#ifndef GL_MAX_SHADER_STORAGE_BLOCK_SIZE
+# define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
+#endif
+
+#ifndef GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT
+# define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#endif
+
+
+// Polygon mode
+#ifndef GL_POINT
+# define GL_POINT 0x1B00
+#endif
+
+#ifndef GL_LINE
+# define GL_LINE 0x1B01
+#endif
+
+#ifndef GL_FILL
+# define GL_FILL 0x1B02
+#endif
+
+
+#ifndef GL_DEPTH_CLAMP
+# define GL_DEPTH_CLAMP 0
+#endif
+
+// Blend functions
+#ifndef GL_SRC1_COLOR
+# define GL_SRC1_COLOR 0x88F9
+#endif
+
+#ifndef GL_ONE_MINUS_SRC1_COLOR
+# define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#endif
+
+#ifndef GL_SOURCE1_ALPHA
+# define GL_SOURCE1_ALPHA 0x8589
+#endif
+
+#ifndef GL_SRC1_ALPHA
+# define GL_SRC1_ALPHA GL_SOURCE1_ALPHA
+#endif
+
+#ifndef GL_ONE_MINUS_SRC1_ALPHA
+# define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#endif
+
+/* ---------------------- GL_ARB_internalformat_query2 --------------------- */
+
+#ifndef GL_INTERNALFORMAT_SUPPORTED
+# define GL_INTERNALFORMAT_SUPPORTED 0x826F
+#endif
+
+// --------------------- Framebuffer SRGB -----------------------
+#ifndef GL_FRAMEBUFFER_SRGB
+# define GL_FRAMEBUFFER_SRGB 0x8DB9
+#endif
+
+// -------------------- Incomplete FBO error codes ---------------
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS
+# define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#endif
+
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER
+# define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#endif
+
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER
+# define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#endif
+
+
+// Define unsupported GL function stubs
+template<typename T>
+void UnsupportedGLFunctionStub( const T &Name )
+{
+ LOG_ERROR_MESSAGE( Name, "() is not supported in this API!\n" );
+}
+
+#ifndef glGenProgramPipelines
+ #define LOAD_GEN_PROGRAM_PIPELINES
+ typedef void (* PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint* pipelines);
+ extern PFNGLGENPROGRAMPIPELINESPROC glGenProgramPipelines;
+#endif
+
+
+#ifndef glDeleteProgramPipelines
+ #define LOAD_GL_DELETE_PROGRAM_PIPELINES
+ typedef void (* PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint* pipelines);
+ extern PFNGLDELETEPROGRAMPIPELINESPROC glDeleteProgramPipelines;
+#endif
+
+#ifndef glBindProgramPipeline
+ #define LOAD_GL_BIND_PROGRAM_PIPELINE
+ typedef void (* PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+ extern PFNGLBINDPROGRAMPIPELINEPROC glBindProgramPipeline;
+#endif
+
+#ifndef glDrawElementsIndirect
+ #define LOAD_DRAW_ELEMENTS_INDIRECT
+ typedef void (* PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const GLvoid *indirect);
+ extern PFNGLDRAWELEMENTSINDIRECTPROC glDrawElementsIndirect;
+#endif
+
+#ifndef glDrawArraysIndirect
+ #define LOAD_DRAW_ARRAYS_INDIRECT
+ typedef void (* PFNGLDRAWARRAYSINDIRECTPROC)( GLenum mode, const GLvoid *indirect );
+ extern PFNGLDRAWARRAYSINDIRECTPROC glDrawArraysIndirect;
+#endif
+
+#ifndef glDispatchComputeIndirect
+ #define LOAD_DISPATCH_COMPUTE_INDIRECT
+ typedef void (* PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+ extern PFNGLDISPATCHCOMPUTEINDIRECTPROC glDispatchComputeIndirect;
+#endif
+
+#ifndef glDrawElementsInstancedBaseVertexBaseInstance
+# define glDrawElementsInstancedBaseVertexBaseInstance(...) UnsupportedGLFunctionStub("glDrawElementsInstancedBaseVertexBaseInstance")
+#endif
+
+#ifndef glDrawElementsInstancedBaseVertex
+# define glDrawElementsInstancedBaseVertex(...) UnsupportedGLFunctionStub("glDrawElementsInstancedBaseVertex")
+#endif
+
+#ifndef glDrawElementsInstancedBaseInstance
+# define glDrawElementsInstancedBaseInstance(...) UnsupportedGLFunctionStub("glDrawElementsInstancedBaseInstance")
+#endif
+
+#ifndef glDrawArraysInstancedBaseInstance
+# define glDrawArraysInstancedBaseInstance(...) UnsupportedGLFunctionStub("glDrawArraysInstancedBaseInstance")
+#endif
+
+#ifndef glDrawElementsBaseVertex
+# define glDrawElementsBaseVertex(...) UnsupportedGLFunctionStub("glDrawElementsBaseVertex")
+#endif
+
+#ifndef glUseProgramStages
+ #define LOAD_GL_USE_PROGRAM_STAGES
+ typedef void (* PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+ extern PFNGLUSEPROGRAMSTAGESPROC glUseProgramStages;
+#endif
+
+#ifndef glTexStorage1D
+# define glTexStorage1D(...) UnsupportedGLFunctionStub("glTexStorage1D")
+#endif
+
+#ifndef glTexSubImage1D
+# define glTexSubImage1D(...) UnsupportedGLFunctionStub("glTexSubImage1D")
+#endif
+
+#ifndef glTexStorage3DMultisample
+# define glTexStorage3DMultisample(...) UnsupportedGLFunctionStub("glTexStorage3DMultisample")
+#endif
+
+#ifndef glTexStorage2DMultisample
+ #define LOAD_GL_TEX_STORAGE_2D_MULTISAMPLE
+ typedef void (* PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+ extern PFNGLTEXSTORAGE2DMULTISAMPLEPROC glTexStorage2DMultisample;
+#endif
+
+#ifndef glTextureView
+# define glTextureView(...) UnsupportedGLFunctionStub("glTextureView")
+#endif
+
+#ifndef glTexBuffer
+ #define LOAD_GL_TEX_BUFFER
+ typedef void (* PFNGLTEXBUFFERPROC) (GLenum, GLenum, GLuint);
+ extern PFNGLTEXBUFFERPROC glTexBuffer;
+#endif
+
+#ifndef glProgramUniform1i
+ #define LOAD_GL_PROGRAM_UNIFORM_1I
+ typedef void (* PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint x);
+ extern PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i;
+#endif
+
+#ifndef glGetProgramInterfaceiv
+ #define LOAD_GL_GET_PROGRAM_INTERFACEIV
+ typedef void (* PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint* params);
+ extern PFNGLGETPROGRAMINTERFACEIVPROC glGetProgramInterfaceiv;
+#endif
+
+#ifndef glGetProgramResourceName
+ #define LOAD_GL_GET_PROGRAM_RESOURCE_NAME
+ typedef void (* PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, GLchar *name);
+ extern PFNGLGETPROGRAMRESOURCENAMEPROC glGetProgramResourceName;
+#endif
+
+#ifndef glGetProgramResourceiv
+ #define LOAD_GL_GET_PROGRAM_RESOURCEIV
+ typedef void (* PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum* props, GLsizei bufSize, GLsizei *length, GLint *params);
+ extern PFNGLGETPROGRAMRESOURCEIVPROC glGetProgramResourceiv;
+#endif
+
+#ifndef glPolygonMode
+ #define LOAD_GL_POLYGON_MODE
+ typedef void (* PFNGLPOLYGONMODE) (GLenum face, GLenum mode);
+ extern PFNGLPOLYGONMODE glPolygonMode;
+#endif
+
+
+#ifndef glEnablei
+ #define LOAD_GL_ENABLEI
+ typedef void (* PFNGLENABLEIPROC) (GLenum, GLuint);
+ extern PFNGLENABLEIPROC glEnablei;
+#endif
+
+#ifndef glBlendFuncSeparatei
+ #define LOAD_GL_BLEND_FUNC_SEPARATEI
+ typedef void (* PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+ extern PFNGLBLENDFUNCSEPARATEIPROC glBlendFuncSeparatei;
+#endif
+
+#ifndef glBlendEquationSeparatei
+ #define LOAD_GL_BLEND_EQUATION_SEPARATEI
+ typedef void (* PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+ extern PFNGLBLENDEQUATIONSEPARATEIPROC glBlendEquationSeparatei;
+#endif
+
+#ifndef glDisablei
+ #define LOAD_GL_DISABLEI
+ typedef void (* PFNGLDISABLEIPROC) (GLenum, GLuint);
+ extern PFNGLDISABLEIPROC glDisablei;
+#endif
+
+#ifndef glColorMaski
+ #define LOAD_GL_COLOR_MASKI
+ typedef void (* PFNGLCOLORMASKIPROC) (GLuint, GLboolean, GLboolean, GLboolean, GLboolean);
+ extern PFNGLCOLORMASKIPROC glColorMaski;
+#endif
+
+#ifndef glViewportIndexedf
+ #define LOAD_GL_VIEWPORT_INDEXEDF
+ typedef void (* PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+ extern PFNGLVIEWPORTINDEXEDFPROC glViewportIndexedf;
+#endif
+
+#ifndef glScissorIndexed
+ #define LOAD_GL_SCISSOR_INDEXED
+ typedef void (* PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+ extern PFNGLSCISSORINDEXEDPROC glScissorIndexed;
+#endif
+
+#ifndef glFramebufferTexture
+ #define LOAD_GL_FRAMEBUFFER_TEXTURE
+ typedef void (* PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum, GLenum, GLuint, GLint);
+ extern PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture;
+#endif
+
+#ifndef glFramebufferTexture1D
+ #define LOAD_GL_FRAMEBUFFER_TEXTURE_1D
+ typedef void (* PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+ extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
+#endif
+
+#ifndef glFramebufferTexture3D
+ #define LOAD_GL_FRAMEBUFFER_TEXTURE_3D
+ typedef void (* PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer);
+ extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
+#endif
+
+#ifndef glCopyImageSubData
+ #define LOAD_GL_COPY_IMAGE_SUB_DATA
+ typedef void (* PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+ extern PFNGLCOPYIMAGESUBDATAPROC glCopyImageSubData;
+#endif
+
+void LoadGLFunctions(); \ No newline at end of file
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.h b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.h
new file mode 100644
index 00000000..a5b381f8
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.h
@@ -0,0 +1,241 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+namespace Diligent
+{
+
+inline GLenum PrimitiveTopologyToGLTopology(PRIMITIVE_TOPOLOGY PrimTopology)
+{
+ switch(PrimTopology)
+ {
+ case PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: return GL_TRIANGLES; break;
+ case PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: return GL_TRIANGLE_STRIP; break;
+ case PRIMITIVE_TOPOLOGY_POINT_LIST: return GL_POINTS; break;
+ case PRIMITIVE_TOPOLOGY_LINE_LIST: return GL_LINES; break;
+ default: return 0;
+ }
+}
+
+inline GLenum TypeToGLType(VALUE_TYPE Value)
+{
+ switch(Value)
+ {
+ case VT_INT8: return GL_BYTE; break;
+ case VT_INT16: return GL_SHORT; break;
+ case VT_INT32: return GL_INT; break;
+ case VT_UINT8: return GL_UNSIGNED_BYTE; break;
+ case VT_UINT16: return GL_UNSIGNED_SHORT; break;
+ case VT_UINT32: return GL_UNSIGNED_INT; break;
+ case VT_FLOAT32: return GL_FLOAT; break;
+ default: return 0;
+ }
+}
+
+inline GLenum UsageToGLUsage(USAGE Usage)
+{
+ // http://www.informit.com/articles/article.aspx?p=2033340&seqNum=2
+ switch(Usage)
+ {
+ case USAGE_STATIC: return GL_STATIC_DRAW;
+ case USAGE_DEFAULT: return GL_DYNAMIC_DRAW;
+ case USAGE_DYNAMIC: return GL_STREAM_DRAW;
+ case USAGE_CPU_ACCESSIBLE: return GL_DYNAMIC_READ;
+ default: UNEXPECTED( "Unknow usage" ); return 0;
+ }
+}
+
+inline void FilterTypeToGLFilterType(FILTER_TYPE Filter, GLenum &GLFilter, Bool &bIsAnisotropic, Bool &bIsComparison)
+{
+ switch(Filter)
+ {
+ case FILTER_TYPE_UNKNOWN:
+ UNEXPECTED( "Unspecified filter type" );
+ bIsAnisotropic = false;
+ bIsComparison = false;
+ GLFilter = GL_NEAREST;
+ break;
+
+ case FILTER_TYPE_POINT:
+ bIsAnisotropic = false;
+ bIsComparison = false;
+ GLFilter = GL_NEAREST;
+ break;
+
+ case FILTER_TYPE_LINEAR:
+ bIsAnisotropic = false;
+ bIsComparison = false;
+ GLFilter = GL_LINEAR;
+ break;
+
+ case FILTER_TYPE_ANISOTROPIC:
+ bIsAnisotropic = true;
+ bIsComparison = false;
+ GLFilter = GL_LINEAR;
+ break;
+
+ case FILTER_TYPE_COMPARISON_POINT:
+ bIsAnisotropic = false;
+ bIsComparison = true;
+ GLFilter = GL_NEAREST;
+ break;
+
+ case FILTER_TYPE_COMPARISON_LINEAR:
+ bIsAnisotropic = false;
+ bIsComparison = true;
+ GLFilter = GL_LINEAR;
+ break;
+
+ case FILTER_TYPE_COMPARISON_ANISOTROPIC:
+ bIsAnisotropic = true;
+ bIsComparison = true;
+ GLFilter = GL_LINEAR;
+ break;
+
+ default:
+ bIsAnisotropic = false;
+ bIsComparison = false;
+ UNEXPECTED( "Unknown filter type" );
+ GLFilter = GL_NEAREST;
+ break;
+ }
+}
+
+GLenum TexFormatToGLInternalTexFormat(TEXTURE_FORMAT TexFormat, Uint32 BindFlags = 0);
+GLenum CorrectGLTexFormat(GLenum GLTexFormat, Uint32 BindFlags);
+
+inline GLenum TexAddressModeToGLAddressMode(TEXTURE_ADDRESS_MODE Mode)
+{
+ switch(Mode)
+ {
+ case TEXTURE_ADDRESS_UNKNOWN: UNEXPECTED( "Texture address mode is not specified" ); return GL_CLAMP_TO_EDGE;
+ case TEXTURE_ADDRESS_WRAP: return GL_REPEAT;
+ case TEXTURE_ADDRESS_MIRROR: return GL_MIRRORED_REPEAT;
+ case TEXTURE_ADDRESS_CLAMP: return GL_CLAMP_TO_EDGE;
+ case TEXTURE_ADDRESS_BORDER: return GL_CLAMP_TO_BORDER;
+ case TEXTURE_ADDRESS_MIRROR_ONCE: return GL_MIRROR_CLAMP_TO_EDGE; // only available with OpenGL 4.4
+ // This mode seems to be different from D3D11_TEXTURE_ADDRESS_MIRROR_ONCE
+ // The texture coord is clamped to the [-1, 1] range, but mirrors the
+ // negative direction with the positive. Basically, it acts as
+ // GL_CLAMP_TO_EDGE except that it takes the absolute value of the texture
+ // coordinates before clamping.
+ default: UNEXPECTED( "Unknown texture address mode" ); return GL_CLAMP_TO_EDGE;
+ }
+}
+
+inline GLenum CompareFuncToGLCompareFunc(COMPARISON_FUNCTION Func)
+{
+ switch(Func)
+ {
+ case COMPARISON_FUNC_UNKNOW: UNEXPECTED( "Comparison function is not specified" ); return GL_ALWAYS;
+ case COMPARISON_FUNC_NEVER: return GL_NEVER;
+ case COMPARISON_FUNC_LESS: return GL_LESS;
+ case COMPARISON_FUNC_EQUAL: return GL_EQUAL;
+ case COMPARISON_FUNC_LESS_EQUAL: return GL_LEQUAL;
+ case COMPARISON_FUNC_GREATER: return GL_GREATER;
+ case COMPARISON_FUNC_NOT_EQUAL: return GL_NOTEQUAL;
+ case COMPARISON_FUNC_GREATER_EQUAL: return GL_GEQUAL;
+ case COMPARISON_FUNC_ALWAYS: return GL_ALWAYS;
+ default: UNEXPECTED( "Unknown comparison func" ); return GL_ALWAYS;
+ }
+}
+
+struct NativePixelAttribs
+{
+ GLenum PixelFormat;
+ GLenum DataType;
+ Bool IsCompressed;
+ explicit NativePixelAttribs(GLenum _PixelFormat = 0, GLenum _DataType = 0, Bool _IsCompressed = False) :
+ PixelFormat(_PixelFormat),
+ DataType(_DataType),
+ IsCompressed(_IsCompressed)
+ {}
+};
+
+inline Uint32 GetNumPixelFormatComponents(GLenum Format)
+{
+ switch(Format)
+ {
+ case GL_RGBA:
+ case GL_RGBA_INTEGER:
+ return 4;
+
+ case GL_RGB:
+ case GL_RGB_INTEGER:
+ return 3;
+
+ case GL_RG:
+ case GL_RG_INTEGER:
+ return 2;
+
+ case GL_RED:
+ case GL_RED_INTEGER:
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL:
+ return 1;
+
+ default: UNEXPECTED( "Unknonw pixel format" ); return 0;
+ };
+}
+
+inline Uint32 GetPixelTypeSize(GLenum Type)
+{
+ switch(Type)
+ {
+ case GL_FLOAT: return sizeof(GLfloat);
+
+ case GL_UNSIGNED_INT_10_10_10_2:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL_UNSIGNED_INT_24_8:
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ case GL_UNSIGNED_INT: return sizeof(GLuint);
+
+ case GL_INT: return sizeof(GLint);
+ case GL_HALF_FLOAT: return sizeof(GLhalf);
+
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ case GL_UNSIGNED_SHORT: return sizeof(GLushort);
+
+ case GL_SHORT: return sizeof(GLshort);
+ case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
+ case GL_BYTE: return sizeof(GLbyte);
+
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:return sizeof(GLfloat) + sizeof(GLuint);
+
+ default: UNEXPECTED( "Unknonw pixel type" ); return 0;
+ }
+}
+
+NativePixelAttribs GetNativePixelTransferAttribs(TEXTURE_FORMAT TexFormat);
+GLenum AccessFlags2GLAccess( Uint32 UAVAccessFlags );
+GLenum TypeToGLTexFormat( VALUE_TYPE ValType, Uint32 NumComponents, Bool bIsNormalized );
+GLenum StencilOp2GlStencilOp( STENCIL_OP StencilOp );
+GLenum BlendFactor2GLBlend( BLEND_FACTOR bf );
+GLenum BlendOperation2GLBlendOp( BLEND_OPERATION BlendOp );
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/HLSL2GLSLConverter.h b/Graphics/GraphicsEngineOpenGL/include/HLSL2GLSLConverter.h
new file mode 100644
index 00000000..6877cc47
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/HLSL2GLSLConverter.h
@@ -0,0 +1,424 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "Shader.h"
+#include "HashUtils.h"
+#include <list>
+#include <unordered_set>
+
+namespace Diligent
+{
+ struct FunctionStubHashKey
+ {
+ FunctionStubHashKey(const String& _Obj, const String& _Func, Uint32 _NumArgs) :
+ Object(_Obj),
+ Function(_Func),
+ NumArguments(_NumArgs)
+ {
+ }
+
+ FunctionStubHashKey(const Char* _Obj, const Char* _Func, Uint32 _NumArgs) :
+ Object(_Obj),
+ Function(_Func),
+ NumArguments(_NumArgs)
+ {
+ }
+
+ FunctionStubHashKey( FunctionStubHashKey && Key ) :
+ Object(std::move(Key.Object)),
+ Function(std::move(Key.Function)),
+ NumArguments(Key.NumArguments)
+ {
+ }
+
+ bool operator==(const FunctionStubHashKey& rhs)const
+ {
+ return Object == rhs.Object &&
+ Function == rhs.Function &&
+ NumArguments == rhs.NumArguments;
+ }
+
+ HashMapStringKey Object;
+ HashMapStringKey Function;
+ Uint32 NumArguments;
+ };
+}
+
+namespace std
+{
+ template<>struct hash < Diligent::FunctionStubHashKey >
+ {
+ size_t operator()( const Diligent::FunctionStubHashKey &Key ) const
+ {
+ return ComputeHash(Key.Object, Key.Function, Key.NumArguments);
+ }
+ };
+}
+
+namespace Diligent
+{
+ class HLSL2GLSLConverter
+ {
+ public:
+ HLSL2GLSLConverter(IShaderSourceInputStreamFactory *pSourceStreamFactory);
+ String Convert(const Char* HLSLSource, size_t NumSymbols, const Char* EntryPoint, SHADER_TYPE ShaderType);
+
+ private:
+ void InsertIncludes(String &GLSLSource);
+
+ void ProcessShaderDeclaration(const Char* EntryPoint, SHADER_TYPE ShaderType);
+
+ IShaderSourceInputStreamFactory* m_pSourceStreamFactory;
+
+ struct HLSLObjectInfo
+ {
+ String GLSLType; // sampler2D, sampler2DShadow, image2D, etc.
+ Uint32 NumComponents; // 0,1,2,3 or 4
+ // Texture2D<float4> -> 4
+ // Texture2D<uint> -> 1
+ // Texture2D -> 0
+ HLSLObjectInfo( const String& Type, Uint32 NComp ) :
+ GLSLType( Type ),
+ NumComponents( NComp )
+ {}
+ };
+ typedef std::unordered_map<HashMapStringKey, HLSLObjectInfo> ObjectsTypeHashType;
+
+ // Stack of parsed objects, for every scope level.
+ // There are currently only two levels:
+ // level 0 - global scope, contains all global objects
+ // (textures, buffers)
+ // level 1 - function body, contains all objects
+ // defined as function arguments
+ std::vector< ObjectsTypeHashType > m_Objects;
+
+ struct GLSLStubInfo
+ {
+ String Name;
+ String Swizzle;
+ GLSLStubInfo( const String& _Name, const char* _Swizzle ) :
+ Name( _Name ),
+ Swizzle( _Swizzle )
+ {}
+ };
+ // Hash map that maps GLSL object, method and number of arguments
+ // passed to the original function, to the GLSL stub function
+ // Example: {"sampler2D", "Sample", 2} -> {"Sample_2", "_SWIZZLE"}
+ std::unordered_map<FunctionStubHashKey, GLSLStubInfo> m_GLSLStubs;
+
+
+ void Tokenize(const String &Source);
+
+ String BuildGLSLSource();
+
+ enum class TokenType
+ {
+ Undefined,
+ PreprocessorDirective,
+ Operator,
+ OpenBrace,
+ ClosingBrace,
+ OpenBracket,
+ ClosingBracket,
+ OpenStaple,
+ ClosingStaple,
+ OpenAngleBracket,
+ ClosingAngleBracket,
+ Identifier,
+ NumericConstant,
+ Semicolon,
+ Comma,
+ cbuffer,
+ Texture1D,
+ Texture1DArray,
+ Texture2D,
+ Texture2DArray,
+ Texture3D,
+ TextureCube,
+ TextureCubeArray,
+ Texture2DMS,
+ Texture2DMSArray,
+ RWTexture1D,
+ RWTexture1DArray,
+ RWTexture2D,
+ RWTexture2DArray,
+ RWTexture3D,
+ SamplerState,
+ SamplerComparisonState,
+ BuiltInType,
+ TextBlock,
+ _struct,
+ Assignment,
+ ComparisonOp,
+ BooleanOp,
+ BitwiseOp,
+ IncDecOp,
+ MathOp,
+ FlowControl
+ };
+
+ struct TokenInfo
+ {
+ TokenType Type;
+ String Literal;
+ String Delimiter;
+ TokenInfo(TokenType _Type = TokenType :: Undefined,
+ const Char* _Literal = "",
+ const Char* _Delimiter = "") :
+ Type( _Type ),
+ Literal( _Literal ),
+ Delimiter(_Delimiter)
+ {}
+ };
+
+ typedef std::list<TokenInfo> TokenListType;
+ typedef std::unordered_map<String, bool> SamplerHashType;
+
+ const HLSLObjectInfo *FindHLSLObject(const String &Name );
+
+ void ProcessObjectMethods(const TokenListType::iterator &ScopeStart, const TokenListType::iterator &ScopeEnd);
+
+ void ProcessRWTextures(const TokenListType::iterator &ScopeStart, const TokenListType::iterator &ScopeEnd);
+
+ void ProcessAtomics(const TokenListType::iterator &ScopeStart,
+ const TokenListType::iterator &ScopeEnd);
+
+ void ProcessScope(const TokenListType::iterator &ScopeStart,
+ const TokenListType::iterator &ScopeEnd);
+
+ void ProcessConstantBuffer(TokenListType::iterator &Token);
+ void ParseSamplers(TokenListType::iterator &ScopeStart, SamplerHashType &SamplersHash);
+ void ProcessTextureDeclaration(TokenListType::iterator &Token, const std::vector<SamplerHashType> &SamplersHash, ObjectsTypeHashType &Objects);
+ bool ProcessObjectMethod(TokenListType::iterator &Token, const TokenListType::iterator &ScopeStart, const TokenListType::iterator &ScopeEnd);
+ Uint32 CountFunctionArguments(TokenListType::iterator &Token, const TokenListType::iterator &ScopeEnd);
+ bool ProcessRWTextureStore(TokenListType::iterator &Token, const TokenListType::iterator &ScopeEnd);
+ void RemoveFlowControlAttribute(TokenListType::iterator &Token);
+ void RemoveSemantics();
+ void RemoveSpecialShaderAttributes();
+ void RemoveSemanticsFromBlock(TokenListType::iterator &Token, TokenType OpenBracketType, TokenType ClosingBracketType, bool IsStruct);
+
+ // IteratorType may be String::iterator or String::const_iterator.
+ // While iterator is convertible to const_iterator,
+ // iterator& cannot be converted to const_iterator& (Microsoft compiler allows
+ // such conversion, while gcc does not)
+ template<typename IteratorType>
+ String PrintTokenContext(IteratorType &TargetToken, Int32 NumAdjacentLines);
+
+ struct ShaderParameterInfo
+ {
+ enum class StorageQualifier
+ {
+ Unknown,
+ In,
+ Out
+ }storageQualifier;
+ String Type;
+ String Name;
+ String Semantic;
+
+ ShaderParameterInfo() :
+ storageQualifier(StorageQualifier::Unknown)
+ {}
+ };
+ void ParseShaderParameters( TokenListType::iterator &Token, std::vector<ShaderParameterInfo>& Params );
+ void ProcessFragmentShaderArguments( std::vector<ShaderParameterInfo>& Params,
+ String &GlobalVariables,
+ String &Epilogue,
+ String &Prologue );
+ void ProcessVertexShaderArguments( std::vector<ShaderParameterInfo>& Params,
+ String &GlobalVariables,
+ String &Epilogue,
+ String &Prologue );
+ void ProcessComputeShaderArguments( TokenListType::iterator &TypeToken,
+ std::vector<ShaderParameterInfo>& Params,
+ String &GlobalVariables,
+ String &Prologue );
+
+ void FindClosingBracket( TokenListType::iterator &Token, const TokenListType::iterator &ScopeEnd, TokenType OpenBracketType, TokenType ClosingBracketType );
+
+ void ProcessReturnStatements( TokenListType::iterator &Token, const String &Epilogue, const char *EntryPoint );
+
+ // Tokenized source code
+ TokenListType m_Tokens;
+
+ // HLSL keyword->token info hash map
+ // Example: "Texture2D" -> TokenInfo(TokenType::Texture2D, "Texture2D")
+ std::unordered_map<HashMapStringKey, TokenInfo> m_HLSLKeywords;
+
+ // Set of all GLSL image types (image1D, uimage1D, iimage1D, image2D, ... )
+ std::unordered_set<HashMapStringKey> m_ImageTypes;
+
+ // Set of all HLSL atomic operations (InterlockedAdd, InterlockedOr, ...)
+ std::unordered_set<HashMapStringKey> m_AtomicOperations;
+ };
+}
+
+// Intro
+// DirectX and OpenGL use different shading languages. While mostly being very similar,
+// the language syntax differ substantially in some places. Having two versions of each
+// shader is clearly not an option for real projects. Maintaining intermediate representation
+// that translates to both languages is one solution, but it might complicate shader development
+// and debugging.
+//
+// HLSL converter allows HLSL shader files to be converted into GLSL source.
+// The entire shader development can thus be performed using HLSL tools. Since no intermediate
+// representation is used, shader files can be directly compiled by HLSL compiler.
+// All tools available for HLSL shader devlopment, analysis and optimization can be
+// used. The source can then be transaprently converted to GLSL.
+//
+//
+// Using HLSL Converter
+// * The following rules are used to convert HLSL texture declaration into GLSL sampler:
+// - HLSL texture dimension defines GLSL sampler dimension:
+// - Texture2D -> sampler2D
+// - TextureCube -> samplerCube
+// - HLSL texture component type defines GLSL sampler type. If no type is specified, float4 is assumed:
+// - Texture2D<float> -> sampler2D
+// - Texture3D<uint4> -> usampler3D
+// - Texture2DArray<int2> -> isampler2DArray
+// - Texture2D -> sampler2D
+// - To distinguish if sampler should be shadow or not, the converter tries to find <Texture Name>_sampler
+// among samplers (global variables and function arguments). If the sampler type is comparison,
+// the texture is converted to shadow sampler. If sampler state is either not comparison or not found,
+// regular sampler is used.
+// Examples:
+// - Texture2D g_ShadowMap; -> sampler2DShadow g_ShadowMap;
+// SamplerComparisonState g_ShadowMap_sampler;
+// - Texture2D g_Tex2D; -> sampler2D g_Tex2D;
+// SamplerState g_Tex2D_sampler;
+// Texture3D g_Tex3D; -> sampler3D g_Tex3D;
+//
+// * GLSL requires format to be specified for all images allowing writes. HLSL converter allows GLSL image
+// format specification inside the special comment block:
+// Example:
+// RWTexture2D<float /* format=r32f */ > Tex2D;
+
+// Requirements:
+// * Shader entry points must be declared as void functions with all outputs listed
+// as out variables
+// ** Members of structures cannot have system-value semantic (such as SV_Position).
+// Such variables must be declared as direct shader input/output
+// * GLSL allows samplers to be declared as global variables or function arguments only.
+// It does not allow local variables of sampler type.
+//
+// Important notes/known issues:
+//
+// * GLSL compiler does not handle float3 structure members correctly. It is
+// strongly suggested not to use this type in structure definitions
+//
+// * At least NVidia GLSL compiler does not apply layout(row_major) to
+// structure members. By default, all matrices in both HLSL and GLSL
+// are column major
+//
+// * GLSL compiler does not properly handle structs passed as function arguments!!!!
+// struct MyStruct
+// {
+// matrix Matr;
+// }
+// void Func(in MyStruct S)
+// {
+// ...
+// mul(f4PosWS, S.Matr); <--- This will not work!!!
+// }
+// DO NOT pass structs to functions, use only built-in types!!!
+//
+// * GLSL does not support most of the implicit type conversions. The following are some
+// examples of required modifications to HLSL code:
+// ** float4 vec = 0; -> float4 vec = float4(0.0, 0.0, 0.0, 0.0);
+// ** float x = 0; -> float x = 0.0;
+// ** uint x = 0; -> uint x = 0u;
+// ** GLES is immensely strict about type conversions. For instance,
+// this code will produce compiler error: float4(0, 0, 0, 0)
+// It must be written as float4(0.0, 0.0, 0.0, 0.0)
+// * GLSL does not support relational and boolean operations on vector types:
+// ** float2 p = float2(1.0,2.0), q = float2(3.0,4.0);
+// bool2 b = x < y; -> Error
+// all(p<q) -> Error
+// ** To facilitate relational and boolean operations on vector types, the following
+// functions are predefined:
+// - Less
+// - LessEqual
+// - Greater
+// - GreaterEqual
+// - Equal
+// - NotEqual
+// - Not
+// - And
+// - Or
+// - BoolToFloat
+// ** Examples:
+// bool2 b = x < y; -> bool2 b = Less(x, y);
+// all(p>=q) -> all( GreaterEqual(p,q) )
+//
+// * When accessing elements of an HLSL matrix, the first index is always row:
+// mat[row][column]
+// In GLSL, the first index is always column:
+// mat[column][row]
+// MATRIX_ELEMENT(mat, row, col) macros is provided to facilitate matrix element retrieval
+
+// * The following functions do not have counterparts in GLSL and should be avoided:
+// ** Texture2DArray.SampleCmpLevelZero()
+// ** TextureCube.SampleCmpLevelZero()
+// ** TextureCubeArray.SampleCmpLevelZero()
+
+
+// * Shader converter creates shader interface blocks to process non-system generated
+// input/output parameters. For instance, to process Out parameter of the vertex
+// shader below
+//
+// struct VSOutput{ ... };
+// void VertexShader(out VSOutput Out){...}
+//
+// the following interface block will be created:
+//
+// out _IntererfaceBlock0
+// {
+// VSOutput Out;
+// };
+//
+// OpenGL requires that interface block definitions in different shader stages
+// must match exaclty: they must define the exact same variables (type/array count
+// and NAME), in the exact same order. Since variable names must match, this
+// effectively means that shader input/output parameter names must also match
+// exactly. This limitation seems to be relaxed in desktop GL and some GLES.
+// For instance, the following code works fine on Desktop GL and on Intel GLES,
+// but fails on NVidia GLES:
+//
+// struct VSOutput{ ... };
+// void VertexShader(out VSOutput Out){...}
+// void PixelShader(in VSOutput In){...}
+//
+// To make it run on NVidia GLES, shader intput/output parameter names must
+// be exactly the same:
+//
+// struct VSOutput{ ... };
+// void VertexShader(out VSOutput VSOut){...}
+// void PixelShader(in VSOutput VSOut){...}
+//
+// Moreover, even when fragment shader does not actually use the parameter,
+// it still must be declared
+//
+// If the requirements above are not met, the shaders are still compiled successfuly,
+// but glDraw*() command fails with useless error 1282 (IVALID_OPERATION) \ No newline at end of file
diff --git a/Graphics/GraphicsEngineOpenGL/include/ProgramPipelineCache.h b/Graphics/GraphicsEngineOpenGL/include/ProgramPipelineCache.h
new file mode 100644
index 00000000..a7b62f49
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/ProgramPipelineCache.h
@@ -0,0 +1,102 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "RenderDevice.h"
+#include "HashUtils.h"
+#include "GLProgram.h"
+
+namespace Diligent
+{
+
+class ProgramPipelineCache
+{
+public:
+ ProgramPipelineCache( class RenderDeviceGLImpl *pRenderDeviceOpenGL );
+ ~ProgramPipelineCache();
+
+ struct CacheElementType
+ {
+ GLObjectWrappers::GLPipelineObj Pipeline;
+ GLProgram Program;
+ CacheElementType() :
+ Pipeline( false ),
+ Program( false )
+ {}
+ CacheElementType( CacheElementType &&Elem ) :
+ Pipeline( std::move( Elem.Pipeline ) ),
+ Program( std::move( Elem.Program ) )
+ {}
+ };
+
+ CacheElementType &GetProgramPipeline( RefCntAutoPtr<IShader> *ppShaders, Uint32 NumShadersToSet );
+ void OnDestroyShader(IShader *pShader);
+
+private:
+ friend class RenderDeviceGLImpl;
+ ThreadingTools::LockFlag m_CacheLockFlag;
+
+ // This structure is used as the key to find VAO
+ struct PipelineCacheKey
+ {
+ IShader *pVS;
+ IShader *pGS;
+ IShader *pPS;
+ IShader *pDS;
+ IShader *pHS;
+ IShader *pCS;
+
+ bool operator == (const PipelineCacheKey &Key)const
+ {
+ return pVS == Key.pVS &&
+ pGS == Key.pGS &&
+ pPS == Key.pPS &&
+ pDS == Key.pDS &&
+ pHS == Key.pHS &&
+ pCS == Key.pCS;
+ }
+ };
+
+ struct PipelineCacheHashFunc
+ {
+ std::size_t operator() ( const PipelineCacheKey& Key )const
+ {
+ std::size_t Seed = 0;
+ if(Key.pVS)HashCombine(Seed, Key.pVS);
+ if(Key.pGS)HashCombine(Seed, Key.pGS);
+ if(Key.pPS)HashCombine(Seed, Key.pPS);
+ if(Key.pDS)HashCombine(Seed, Key.pDS);
+ if(Key.pHS)HashCombine(Seed, Key.pHS);
+ if(Key.pCS)HashCombine(Seed, Key.pCS);
+ return Seed;
+ }
+ };
+
+ bool m_bIsProgramPipelineSupported;
+
+ std::unordered_map<PipelineCacheKey, CacheElementType, PipelineCacheHashFunc> m_Cache;
+ std::unordered_multimap<IShader*, PipelineCacheKey> m_ShaderToKey;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/RasterizerStateGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/RasterizerStateGLImpl.h
new file mode 100644
index 00000000..6e28893a
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/RasterizerStateGLImpl.h
@@ -0,0 +1,46 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "BaseInterfacesGL.h"
+#include "RasterizerStateGL.h"
+#include "RasterizerStateBase.h"
+#include "RenderDevice.h"
+
+namespace Diligent
+{
+
+/// Implementation of the Diligent::IRasterizerStateGL interface
+class RasterizerStateGLImpl : public RasterizerStateBase<IRasterizerStateGL, IGLDeviceBaseInterface>
+{
+public:
+ typedef RasterizerStateBase<IRasterizerStateGL, IGLDeviceBaseInterface> TRasterizerStateBase;
+
+ RasterizerStateGLImpl(class IRenderDevice *pDeviceGL, const RasterizerStateDesc& RasterizerStateDesc, bool bIsDeviceInternal = false );
+ ~RasterizerStateGLImpl();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface );
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLESImpl.h b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLESImpl.h
new file mode 100644
index 00000000..eddcf0b6
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLESImpl.h
@@ -0,0 +1,45 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "RenderDeviceGLImpl.h"
+
+namespace Diligent
+{
+
+class RenderDeviceGLESImpl : public RenderDeviceGLImpl
+{
+public:
+ RenderDeviceGLESImpl( const ContextInitInfo &InitInfo );
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface );
+
+ virtual bool Invalidate();
+
+ virtual void Suspend();
+
+ virtual EGLint Resume( ANativeWindow* window );
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h
new file mode 100644
index 00000000..411df027
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h
@@ -0,0 +1,131 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "RenderDeviceBase.h"
+
+#ifdef _WINDOWS
+#include "GLContextWindows.h"
+#endif
+
+#ifdef ANDROID
+#include "GLContextAndroid.h"
+#endif
+
+#include "VAOCache.h"
+#include "ProgramPipelineCache.h"
+#include "BaseInterfacesGL.h"
+#include "FBOCache.h"
+#include "TexRegionRender.h"
+
+enum class GPU_VENDOR
+{
+ UNKNOWN,
+ INTEL,
+ ATI,
+ NVIDIA
+};
+
+struct GPUInfo
+{
+ GPU_VENDOR Vendor;
+ GPUInfo() :
+ Vendor( GPU_VENDOR::UNKNOWN )
+ {}
+};
+
+namespace Diligent
+{
+
+/// Implementation of the render device interface in OpenGL
+class RenderDeviceGLImpl : public RenderDeviceBase<IGLDeviceBaseInterface>
+{
+public:
+ typedef RenderDeviceBase<IGLDeviceBaseInterface> TRenderDeviceBase;
+
+ RenderDeviceGLImpl( const ContextInitInfo &InitInfo );
+ ~RenderDeviceGLImpl();
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ void CreateBuffer(const BufferDesc& BuffDesc, const BufferData &BuffData, IBuffer **ppBufferLayout, bool bIsDeviceInternal);
+ virtual void CreateBuffer(const BufferDesc& BuffDesc, const BufferData &BuffData, IBuffer **ppBufferLayout)override;
+
+ void CreateVertexDescription( const LayoutDesc& LayoutDesc, IShader *pVertexShader, IVertexDescription **ppVertexDesc, bool bIsDeviceInternal );
+ virtual void CreateVertexDescription( const LayoutDesc& LayoutDesc, IShader *pVertexShader, IVertexDescription **ppVertexDesc )override;
+
+ void CreateShader(const ShaderCreationAttribs &ShaderCreationAttribs, IShader **ppShader, bool bIsDeviceInternal );
+ virtual void CreateShader(const ShaderCreationAttribs &ShaderCreationAttribs, IShader **ppShader)override;
+
+ void CreateTexture(const TextureDesc& TexDesc, const TextureData &Data, ITexture **ppTexture, bool bIsDeviceInternal);
+ virtual void CreateTexture(const TextureDesc& TexDesc, const TextureData &Data, ITexture **ppTexture)override;
+
+ void CreateSampler(const SamplerDesc& SamplerDesc, ISampler **ppSampler, bool bIsDeviceInternal);
+ virtual void CreateSampler(const SamplerDesc& SamplerDesc, ISampler **ppSampler)override;
+
+ void CreateDepthStencilState( const DepthStencilStateDesc &DSSDesc, IDepthStencilState **ppDepthStencilState, bool bIsDeviceInternal );
+ virtual void CreateDepthStencilState( const DepthStencilStateDesc &DSSDesc, IDepthStencilState **ppDepthStencilState )override;
+
+ void CreateRasterizerState( const RasterizerStateDesc &RSDesc, IRasterizerState **ppRasterizerState, bool bIsDeviceInternal);
+ virtual void CreateRasterizerState( const RasterizerStateDesc &RSDesc, IRasterizerState **ppRasterizerState )override;
+
+ void CreateBlendState( const BlendStateDesc &BSDesc, IBlendState **ppBlendState, bool bIsDeviceInternal );
+ virtual void CreateBlendState( const BlendStateDesc &BSDesc, IBlendState **ppBlendState )override;
+
+ const GPUInfo& GetGPUInfo(){ return m_GPUInfo; }
+
+protected:
+ friend class DeviceContextGLImpl;
+ friend class TextureBaseGL;
+ friend class VertexDescGLImpl;
+ friend class ShaderGLImpl;
+ friend class BufferGLImpl;
+ friend class TextureViewGLImpl;
+ friend class SwapChainGLImpl;
+
+ // Must be the first member because its constructor initializes OpenGL
+ GLContext m_GLContext;
+
+ std::unordered_set<String> m_ExtensionStrings;
+
+ VAOCache m_VAOCache;
+ FBOCache m_FBOCache;
+ ProgramPipelineCache m_PipelineCache;
+
+ GPUInfo m_GPUInfo;
+
+ // Any draw command fails if no VAO is bound. We will use this empty
+ // VAO for draw commands with null input layout, such as these that
+ // only use VertexID as input.
+ GLObjectWrappers::GLVertexArrayObj m_EmptyVAO;
+
+ TexRegionRender m_TexRegionRender;
+
+private:
+ virtual void TestTextureFormat( TEXTURE_FORMAT TexFormat );
+ bool CheckExtension(const Char *ExtensionString);
+ void FlagSupportedTexFormats();
+ void QueryDeviceCaps();
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/SamplerGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/SamplerGLImpl.h
new file mode 100644
index 00000000..20b9f505
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/SamplerGLImpl.h
@@ -0,0 +1,52 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "BaseInterfacesGL.h"
+#include "SamplerGL.h"
+#include "SamplerBase.h"
+#include "RenderDevice.h"
+#include "GLObjectWrapper.h"
+
+namespace Diligent
+{
+
+/// Implementation of the Diligent::ISamplerGL interface
+class SamplerGLImpl : public SamplerBase<ISamplerGL, IGLDeviceBaseInterface>
+{
+public:
+ typedef SamplerBase<ISamplerGL, IGLDeviceBaseInterface> TSamplerBase;
+
+ SamplerGLImpl( class RenderDeviceGLImpl *pDeviceGL, const SamplerDesc& SamplerDesc, bool bIsDeviceInternal = false );
+ ~SamplerGLImpl();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface );
+
+ const GLObjectWrappers::GLSamplerObj& GetHandle(){ return m_GlSampler; }
+
+private:
+ GLObjectWrappers::GLSamplerObj m_GlSampler;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h
new file mode 100644
index 00000000..b4f20f21
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h
@@ -0,0 +1,105 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "BaseInterfacesGL.h"
+#include "ShaderGL.h"
+#include "ShaderBase.h"
+#include "RenderDevice.h"
+#include "GLObjectWrapper.h"
+#include "GLProgram.h"
+#include "HashUtils.h"
+
+namespace Diligent
+{
+
+inline GLenum GetGLShaderType(SHADER_TYPE ShaderType)
+{
+ switch(ShaderType)
+ {
+ case SHADER_TYPE_VERTEX: return GL_VERTEX_SHADER; break;
+ case SHADER_TYPE_PIXEL: return GL_FRAGMENT_SHADER; break;
+ case SHADER_TYPE_GEOMETRY: return GL_GEOMETRY_SHADER; break;
+ case SHADER_TYPE_HULL: return GL_TESS_CONTROL_SHADER; break;
+ case SHADER_TYPE_DOMAIN: return GL_TESS_EVALUATION_SHADER; break;
+ case SHADER_TYPE_COMPUTE: return GL_COMPUTE_SHADER; break;
+ default: return 0;
+ }
+}
+
+inline GLenum ShaderTypeToGLShaderBit(SHADER_TYPE ShaderType)
+{
+ switch(ShaderType)
+ {
+ case SHADER_TYPE_VERTEX: return GL_VERTEX_SHADER_BIT; break;
+ case SHADER_TYPE_PIXEL: return GL_FRAGMENT_SHADER_BIT; break;
+ case SHADER_TYPE_GEOMETRY: return GL_GEOMETRY_SHADER_BIT; break;
+ case SHADER_TYPE_HULL: return GL_TESS_CONTROL_SHADER_BIT; break;
+ case SHADER_TYPE_DOMAIN: return GL_TESS_EVALUATION_SHADER_BIT; break;
+ case SHADER_TYPE_COMPUTE: return GL_COMPUTE_SHADER_BIT; break;
+ default: return 0;
+ }
+}
+
+/// Implementation of the Diligent::IShaderGL interface
+class ShaderGLImpl : public ShaderBase<IShaderGL, IGLDeviceBaseInterface>
+{
+public:
+ typedef ShaderBase<IShaderGL, IGLDeviceBaseInterface> TShaderBase;
+
+ ShaderGLImpl( class RenderDeviceGLImpl *pDeviceGL, const ShaderCreationAttribs &ShaderCreationAttribs, bool bIsDeviceInternal = false );
+ ~ShaderGLImpl();
+
+ virtual void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags )override;
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ virtual IShaderVariable* GetShaderVariable( const Char* Name )override;
+
+private:
+ struct CGLShaderVariable : ShaderVariableBase
+ {
+ CGLShaderVariable( ShaderGLImpl *pShader, GLProgram::GLProgramVariableBase &ProgVar ) :
+ ShaderVariableBase( pShader ),
+ ProgramVar(ProgVar)
+ {}
+
+ virtual void Set( IDeviceObject *pObject )override
+ {
+ ProgramVar.pResource = pObject;
+ }
+ private:
+ GLProgram::GLProgramVariableBase &ProgramVar;
+ };
+
+ friend class ProgramPipelineCache;
+ friend class DeviceContextGLImpl;
+ GLProgram m_GlProgObj; // Used if program pipeline supported
+ GLObjectWrappers::GLShaderObj m_GLShaderObj; // Used if program pipelines are not supported
+
+ /// Hash map to look up shader variables by name.
+ std::unordered_map<Diligent::HashMapStringKey, CGLShaderVariable> m_VariableHash;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/SwapChainGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/SwapChainGLImpl.h
new file mode 100644
index 00000000..582a80d3
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/SwapChainGLImpl.h
@@ -0,0 +1,50 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "SwapChainGL.h"
+#include "SwapChainBase.h"
+
+namespace Diligent
+{
+
+/// Implementation of the Diligent::ISwapChainGL interface
+class SwapChainGLImpl : public SwapChainBase<ISwapChainGL>
+{
+public:
+ typedef SwapChainBase<ISwapChainGL> TSwapChainBase;
+
+ SwapChainGLImpl(const SwapChainDesc& SwapChainDesc,
+ class RenderDeviceGLImpl* pRenderDeviceGL,
+ class DeviceContextGLImpl* pImmediateContextGL);
+ ~SwapChainGLImpl();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface );
+
+ virtual void Present();
+
+ virtual void Resize( Uint32 NewWidth, Uint32 NewHeight );
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/TexRegionRender.h b/Graphics/GraphicsEngineOpenGL/include/TexRegionRender.h
new file mode 100644
index 00000000..a16ea719
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/TexRegionRender.h
@@ -0,0 +1,66 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+namespace Diligent
+{
+
+// Helper class to facilitate texture copying by rendering
+class TexRegionRender
+{
+public:
+ TexRegionRender(class RenderDeviceGLImpl *pDeviceGL);
+ void SetStates(class DeviceContextGLImpl *pCtxGL);
+ void RestoreStates(class DeviceContextGLImpl *pCtxGL);
+ void Render(class DeviceContextGLImpl *pCtxGL,
+ ITextureView *pSrcSRV,
+ TEXTURE_TYPE TexType,
+ TEXTURE_FORMAT TexFormat,
+ Int32 DstToSrcXOffset,
+ Int32 DstToSrcYOffset,
+ Int32 SrcZ,
+ Int32 SrcMipLevel);
+
+private:
+ Diligent::RefCntAutoPtr<IShader> m_pVertexShader;
+ Diligent::RefCntAutoPtr<IShader> m_pFragmentShaders[TEXTURE_TYPE_NUM_TYPES * 3];
+ Diligent::RefCntAutoPtr<IBuffer> m_pConstantBuffer;
+ Diligent::RefCntAutoPtr<IRasterizerState> m_pSolidFillNoCullRS;
+ Diligent::RefCntAutoPtr<IDepthStencilState> m_pDisableDetphDS;
+ Diligent::RefCntAutoPtr<IBlendState> m_pDefaultBS;
+
+ Diligent::RefCntAutoPtr<IRasterizerState> m_pOrigRS;
+ Diligent::RefCntAutoPtr<IDepthStencilState> m_pOrigDS;
+ Uint32 m_OrigStencilRef;
+ Diligent::RefCntAutoPtr<IBlendState> m_pOrigBS;
+ float m_OrigBlendFactors[4];
+ Uint32 m_OrigSamplesBlendMask;
+ Uint32 m_NumRenderTargets;
+ ITextureView *m_pOrigRTVs[MaxRenderTargets];
+ Diligent::RefCntAutoPtr<ITextureView> m_pOrigDSV;
+ std::vector<IShader*> m_pOrigShaders;
+ std::vector<Viewport> m_OrigViewports;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/Texture1DArray_OGL.h b/Graphics/GraphicsEngineOpenGL/include/Texture1DArray_OGL.h
new file mode 100644
index 00000000..707d91c3
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/Texture1DArray_OGL.h
@@ -0,0 +1,48 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "TextureBaseGL.h"
+
+namespace Diligent
+{
+
+class Texture1DArray_OGL : public TextureBaseGL
+{
+public:
+ Texture1DArray_OGL( class RenderDeviceGLImpl *pDeviceGL,
+ class DeviceContextGLImpl *pDeviceContext,
+ const TextureDesc& BuffDesc,
+ const TextureData &InitData = TextureData(),
+ bool bIsDeviceInternal = false);
+ ~Texture1DArray_OGL();
+
+ virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData );
+ virtual void AttachToFramebuffer( const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint );
+
+private:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/Texture1D_OGL.h b/Graphics/GraphicsEngineOpenGL/include/Texture1D_OGL.h
new file mode 100644
index 00000000..33b9a780
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/Texture1D_OGL.h
@@ -0,0 +1,48 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "TextureBaseGL.h"
+
+namespace Diligent
+{
+
+class Texture1D_OGL : public TextureBaseGL
+{
+public:
+ Texture1D_OGL( class RenderDeviceGLImpl *pDeviceGL,
+ class DeviceContextGLImpl *pDeviceContext,
+ const TextureDesc& BuffDesc,
+ const TextureData &InitData = TextureData(),
+ bool bIsDeviceInternal = false);
+ ~Texture1D_OGL();
+
+ virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData );
+ virtual void AttachToFramebuffer( const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint );
+
+private:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/Texture2DArray_OGL.h b/Graphics/GraphicsEngineOpenGL/include/Texture2DArray_OGL.h
new file mode 100644
index 00000000..9c7c896f
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/Texture2DArray_OGL.h
@@ -0,0 +1,48 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "TextureBaseGL.h"
+
+namespace Diligent
+{
+
+class Texture2DArray_OGL : public TextureBaseGL
+{
+public:
+ Texture2DArray_OGL( class RenderDeviceGLImpl *pDeviceGL,
+ class DeviceContextGLImpl *pDeviceContext,
+ const TextureDesc& BuffDesc,
+ const TextureData &InitData = TextureData(),
+ bool bIsDeviceInternal = false );
+ ~Texture2DArray_OGL();
+
+ virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData );
+ virtual void AttachToFramebuffer( const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint );
+
+private:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/Texture2D_OGL.h b/Graphics/GraphicsEngineOpenGL/include/Texture2D_OGL.h
new file mode 100644
index 00000000..ab9225b9
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/Texture2D_OGL.h
@@ -0,0 +1,48 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "TextureBaseGL.h"
+
+namespace Diligent
+{
+
+class Texture2D_OGL : public TextureBaseGL
+{
+public:
+ Texture2D_OGL( class RenderDeviceGLImpl *pDeviceGL,
+ class DeviceContextGLImpl *pDeviceContext,
+ const TextureDesc& BuffDesc,
+ const TextureData &InitData = TextureData(),
+ bool bIsDeviceInternal = false);
+ ~Texture2D_OGL();
+
+ virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData );
+ virtual void AttachToFramebuffer( const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint );
+
+private:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/Texture3D_OGL.h b/Graphics/GraphicsEngineOpenGL/include/Texture3D_OGL.h
new file mode 100644
index 00000000..83e9a257
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/Texture3D_OGL.h
@@ -0,0 +1,48 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "TextureBaseGL.h"
+
+namespace Diligent
+{
+
+class Texture3D_OGL : public TextureBaseGL
+{
+public:
+ Texture3D_OGL( class RenderDeviceGLImpl *pDeviceGL,
+ class DeviceContextGLImpl *pDeviceContext,
+ const TextureDesc& BuffDesc,
+ const TextureData &InitData = TextureData(),
+ bool bIsDeviceInternal = false );
+ ~Texture3D_OGL();
+
+ virtual void UpdateData(IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData);
+ virtual void AttachToFramebuffer( const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint );
+
+private:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h
new file mode 100644
index 00000000..0cc49ac1
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h
@@ -0,0 +1,83 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "BaseInterfacesGL.h"
+#include "TextureGL.h"
+#include "TextureBase.h"
+#include "RenderDevice.h"
+#include "GLObjectWrapper.h"
+#include "TextureViewGLImpl.h"
+#include "AsyncWritableResource.h"
+
+namespace Diligent
+{
+
+/// Base implementation of the Diligent::ITextureGL interface
+class TextureBaseGL : public TextureBase<ITextureGL, TextureViewGLImpl>, public AsyncWritableResource
+{
+public:
+ typedef TextureBase<ITextureGL, TextureViewGLImpl> TTextureBase;
+
+ TextureBaseGL(class RenderDeviceGLImpl *pDeviceGL, const TextureDesc& BuffDesc, const TextureData &InitData = TextureData(), bool bIsDeviceInternal = false);
+ ~TextureBaseGL();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )override;
+
+ //virtual void CopyData(CTexture *pSrcTexture, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size);
+ virtual void Map( IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapFlags, PVoid &pMappedData )override;
+ virtual void Unmap( IDeviceContext *pContext )override;
+
+ const GLObjectWrappers::GLTextureObj& GetGLHandle()const{ return m_GlTexture; }
+ GLenum GetBindTarget()const{return m_BindTarget;}
+ GLenum GetGLTexFormat()const{ return m_GLTexFormat; }
+
+ void TextureMemoryBarrier( Uint32 RequiredBarriers, class GLContextState &GLContextState);
+
+ virtual void AttachToFramebuffer(const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint) = 0;
+
+ virtual void CopyData(IDeviceContext *pContext,
+ ITexture *pSrcTexture,
+ Uint32 SrcMipLevel,
+ Uint32 SrcSlice,
+ const Box *pSrcBox,
+ Uint32 DstMipLevel,
+ Uint32 DstSlice,
+ Uint32 DstX,
+ Uint32 DstY,
+ Uint32 DstZ)override;
+
+protected:
+ virtual void CreateViewInternal( const struct TextureViewDesc &ViewDesc, class ITextureView **ppView, bool bIsDefaultView )override;
+ void SetDefaultGLParameters();
+
+ GLObjectWrappers::GLTextureObj m_GlTexture;
+ GLenum m_BindTarget;
+ GLenum m_GLTexFormat;
+ //Uint32 m_uiMapTarget;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/TextureViewGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/TextureViewGLImpl.h
new file mode 100644
index 00000000..4284eaaf
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/TextureViewGLImpl.h
@@ -0,0 +1,60 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "BaseInterfacesGL.h"
+#include "TextureViewGL.h"
+#include "TextureViewBase.h"
+#include "RenderDevice.h"
+#include "GLObjectWrapper.h"
+
+namespace Diligent
+{
+
+/// Implementation of the Diligent::ITextureViewGL interface
+class TextureViewGLImpl : public TextureViewBase<ITextureViewGL>
+{
+public:
+ typedef TextureViewBase<ITextureViewGL> TTextureViewBase;
+
+ TextureViewGLImpl( class IRenderDevice *pDevice,
+ const struct TextureViewDesc& ViewDesc,
+ class TextureBaseGL *pTexture,
+ bool bCreateGLViewTex,
+ bool bIsDefaultView );
+ ~TextureViewGLImpl();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ const GLObjectWrappers::GLTextureObj& GetHandle();
+ GLenum GetBindTarget();
+
+ void GenerateMips( IDeviceContext *pContext )override;
+
+protected:
+ GLObjectWrappers::GLTextureObj m_ViewTexGLHandle;
+ GLenum m_ViewTexBindTarget;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/VAOCache.h b/Graphics/GraphicsEngineOpenGL/include/VAOCache.h
new file mode 100644
index 00000000..2604fbcc
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/VAOCache.h
@@ -0,0 +1,103 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "GraphicsTypes.h"
+#include "Buffer.h"
+#include "VertexDescription.h"
+#include "LockHelper.h"
+#include "HashUtils.h"
+#include "DeviceContextBase.h"
+#include "BaseInterfacesGL.h"
+
+namespace Diligent
+{
+
+class VAOCache
+{
+public:
+ VAOCache();
+ ~VAOCache();
+
+ const GLObjectWrappers::GLVertexArrayObj& GetVAO( IVertexDescription &VertexDesc,
+ IBuffer *pIndexBuffer,
+ vector< VertexStreamInfo > &VertexStreams,
+ class GLContextState &GLContextState);
+ void OnDestroyBuffer(IBuffer *pBuffer);
+ void OnDestroyVertexDesc(IVertexDescription *pVertexDesc);
+
+private:
+ // This structure is used as the key to find VAO
+ struct VAOCacheKey
+ {
+ // Note that the the pointers are used for ordering only
+ // They are not used to access the objects
+ IVertexDescription* pVertexDesc;
+ IBuffer* pIndexBuffer;
+ struct StreamAttribs
+ {
+ IBuffer* pBuffer;
+ Uint32 Stride;
+ Uint32 Offset;
+ }Streams[MaxBufferSlots];
+
+ bool operator == (const VAOCacheKey &Key)const
+ {
+ return (pVertexDesc == Key.pVertexDesc) &&
+ (pIndexBuffer == Key.pIndexBuffer) &&
+ (memcmp(Streams, Key.Streams, sizeof(Streams)) == 0);
+ }
+ };
+
+ struct VAOCacheKeyHashFunc
+ {
+ std::size_t operator() ( const VAOCacheKey& Key )const
+ {
+ std::size_t Seed = 0;
+ HashCombine(Seed, Key.pVertexDesc);
+ if(Key.pIndexBuffer)
+ HashCombine(Seed, Key.pIndexBuffer);
+ for(int iStream = 0; iStream < _countof(Key.Streams); ++iStream )
+ {
+ auto &CurrStream = Key.Streams[iStream];
+ if( CurrStream.pBuffer )
+ {
+ HashCombine(Seed, CurrStream.pBuffer);
+ HashCombine(Seed, CurrStream.Offset);
+ HashCombine(Seed, CurrStream.Stride);
+ }
+ }
+ return Seed;
+ }
+ };
+
+
+ friend class RenderDeviceGLImpl;
+ ThreadingTools::LockFlag m_CacheLockFlag;
+ std::unordered_map<VAOCacheKey, GLObjectWrappers::GLVertexArrayObj, VAOCacheKeyHashFunc> m_Cache;
+ std::unordered_multimap<IVertexDescription*, VAOCacheKey> m_VertexDescToKey;
+ std::unordered_multimap<IBuffer*, VAOCacheKey> m_BuffToKey;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/VertexDescGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/VertexDescGLImpl.h
new file mode 100644
index 00000000..1953e044
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/VertexDescGLImpl.h
@@ -0,0 +1,50 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "BaseInterfacesGL.h"
+#include "VertexDescriptionGL.h"
+#include "VertexDescriptionBase.h"
+#include "BaseInterfacesGL.h"
+#include "RenderDevice.h"
+
+namespace Diligent
+{
+
+/// Implementation of the Diligent::IVertexDescriptionGL interface
+class VertexDescGLImpl : public VertexDescriptionBase<IVertexDescriptionGL>
+{
+public:
+ typedef VertexDescriptionBase<IVertexDescriptionGL> TVertexDescriptionBase;
+
+ VertexDescGLImpl( class RenderDeviceGLImpl *pDeviceGL, const LayoutDesc &LayoutDesc, bool bIsDeviceInternal = false );
+ ~VertexDescGLImpl();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface );
+
+private:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/include/pch.h b/Graphics/GraphicsEngineOpenGL/include/pch.h
new file mode 100644
index 00000000..e4530e99
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/include/pch.h
@@ -0,0 +1,96 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include <vector>
+
+#include <map>
+#include <unordered_map>
+#include <unordered_set>
+#include <algorithm>
+
+// Must be defined to use static version of glew
+#ifdef _WINDOWS
+ #define GLEW_STATIC
+ #include "glew.h"
+ // Glew includes <windows.h>
+ #define NOMINMAX
+ #include "wglew.h"
+ #include <GL/GL.h>
+#endif
+
+
+#ifdef ANDROID
+#ifndef USE_GL3_STUB
+ #define USE_GL3_STUB 0
+#endif
+ #if USE_GL3_STUB
+ #include "gl3stub.h"
+ #include <GLES2/gl2platform.h>
+ #else
+ #include <GLES3/gl3.h>
+ #include <GLES3/gl3platform.h>
+ #endif
+#endif
+
+#include "Errors.h"
+
+#ifdef ANDROID
+ // GLStubs must be included after GLFeatures!
+ #include "GLStubs.h"
+#endif
+
+#include "PlatformDefinitions.h"
+#include "RefCntAutoPtr.h"
+#include "DebugUtilities.h"
+#include "GLObjectWrapper.h"
+#include "DebugUtilities.h"
+#include "ValidatedCast.h"
+#include "RenderDevice.h"
+#include "BaseInterfacesGL.h"
+
+using namespace Diligent;
+using namespace std;
+
+#define CHECK_GL_ERROR(...)\
+{ \
+ auto err = glGetError(); \
+ if( err != GL_NO_ERROR ) \
+ { \
+ LogError<false>(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__, "\nGL Error Code: ", err); \
+ UNEXPECTED("Error"); \
+ } \
+}
+
+#define CHECK_GL_ERROR_AND_THROW(...)\
+{ \
+ auto err = glGetError(); \
+ if( err != GL_NO_ERROR ) \
+ LogError<true>(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__, "\nGL Error Code: ", err); \
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/BaseInterfacesGL.h b/Graphics/GraphicsEngineOpenGL/interface/BaseInterfacesGL.h
new file mode 100644
index 00000000..01c0996c
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/BaseInterfacesGL.h
@@ -0,0 +1,48 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#ifdef ANDROID
+ #include "RenderDeviceGLES.h"
+ namespace Diligent
+ {
+ static const Diligent::INTERFACE_ID IID_GLDeviceBaseInterface = IID_RenderDeviceGLES;
+ typedef IRenderDeviceGLES IGLDeviceBaseInterface;
+ }
+#endif
+
+#ifdef _WINDOWS
+ #include "RenderDeviceGL.h"
+ namespace Diligent
+ {
+ static const Diligent::INTERFACE_ID IID_GLDeviceBaseInterface = IID_RenderDeviceGL;
+ typedef IRenderDeviceGL IGLDeviceBaseInterface;
+ }
+#endif
+
+#include "DeviceContextGL.h"
+namespace Diligent
+{
+ typedef IDeviceContextGL IGLDeviceContextBaseInterface;
+} \ No newline at end of file
diff --git a/Graphics/GraphicsEngineOpenGL/interface/BlendStateGL.h b/Graphics/GraphicsEngineOpenGL/interface/BlendStateGL.h
new file mode 100644
index 00000000..8923adf5
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/BlendStateGL.h
@@ -0,0 +1,45 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IBlendStateGL interface
+
+#include "BlendState.h"
+
+namespace Diligent
+{
+
+// {B543F4DC-000F-4EE6-AC06-E6642BBC3560}
+static const Diligent::INTERFACE_ID IID_BlendStateGL =
+{ 0xb543f4dc, 0xf, 0x4ee6, { 0xac, 0x6, 0xe6, 0x64, 0x2b, 0xbc, 0x35, 0x60 } };
+
+/// Interface to the blend state object implemented in OpenGL
+class IBlendStateGL : public Diligent::IBlendState
+{
+public:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/BufferGL.h b/Graphics/GraphicsEngineOpenGL/interface/BufferGL.h
new file mode 100644
index 00000000..33ed7c2b
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/BufferGL.h
@@ -0,0 +1,45 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IBufferGL interface
+
+#include "Buffer.h"
+
+namespace Diligent
+{
+
+// {08DF7319-F425-4EC7-8D2B-1B3FC0BDDBB4}
+static const Diligent::INTERFACE_ID IID_BufferGL =
+{ 0x8df7319, 0xf425, 0x4ec7, { 0x8d, 0x2b, 0x1b, 0x3f, 0xc0, 0xbd, 0xdb, 0xb4 } };
+
+/// Interface to the buffer object implemented in OpenGL
+class IBufferGL : public Diligent::IBuffer
+{
+public:
+ //const GLObjectWrappers::GLBufferObj& GetGLBufferHandle()
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/BufferViewGL.h b/Graphics/GraphicsEngineOpenGL/interface/BufferViewGL.h
new file mode 100644
index 00000000..3124a545
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/BufferViewGL.h
@@ -0,0 +1,45 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IBufferViewGL interface
+
+#include "BufferView.h"
+
+namespace Diligent
+{
+
+// {927A865B-3CEB-4743-9A22-2A1397A73E6D}
+static const Diligent::INTERFACE_ID IID_BufferViewGL =
+{ 0x927a865b, 0x3ceb, 0x4743, { 0x9a, 0x22, 0x2a, 0x13, 0x97, 0xa7, 0x3e, 0x6d } };
+
+/// Interface to the buffer view object implemented in OpenGL
+class IBufferViewGL : public Diligent::IBufferView
+{
+public:
+ //const GLObjectWrappers::GLTextureObj& GetTexBufferHandle(){ return m_GLTexBuffer; }
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/DepthStencilStateGL.h b/Graphics/GraphicsEngineOpenGL/interface/DepthStencilStateGL.h
new file mode 100644
index 00000000..70f568e5
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/DepthStencilStateGL.h
@@ -0,0 +1,45 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IDepthStencilStateGL interface
+
+#include "DepthStencilState.h"
+
+namespace Diligent
+{
+
+// {96946955-33A3-46CA-BB83-207332AFB2A9}
+static const Diligent::INTERFACE_ID IID_DepthStencilStateGL =
+{ 0x96946955, 0x33a3, 0x46ca, { 0xbb, 0x83, 0x20, 0x73, 0x32, 0xaf, 0xb2, 0xa9 } };
+
+/// Interface to the depth stencil state object implemented in OpenGL
+class IDepthStencilStateGL : public Diligent::IDepthStencilState
+{
+public:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/DeviceContextGL.h b/Graphics/GraphicsEngineOpenGL/interface/DeviceContextGL.h
new file mode 100644
index 00000000..12f6f01a
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/DeviceContextGL.h
@@ -0,0 +1,45 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IDeviceContextGL interface
+
+#include "DeviceContext.h"
+
+namespace Diligent
+{
+
+// {3464FDF1-C548-4935-96C3-B454C9DF6F6A}
+static const Diligent::INTERFACE_ID IID_DeviceContextGL =
+{ 0x3464fdf1, 0xc548, 0x4935, { 0x96, 0xc3, 0xb4, 0x54, 0xc9, 0xdf, 0x6f, 0x6a } };
+
+/// Interface to the device context object implemented in OpenGL
+class IDeviceContextGL : public Diligent::IDeviceContext
+{
+public:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/RasterizerStateGL.h b/Graphics/GraphicsEngineOpenGL/interface/RasterizerStateGL.h
new file mode 100644
index 00000000..685dff08
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/RasterizerStateGL.h
@@ -0,0 +1,45 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IRasterizerStateGL interface
+
+#include "RasterizerState.h"
+
+namespace Diligent
+{
+
+// {B546E86A-E68D-4FC5-A7DC-04F8151941D2}
+static const Diligent::INTERFACE_ID IID_RasterizerStateGL =
+{ 0xb546e86a, 0xe68d, 0x4fc5, { 0xa7, 0xdc, 0x4, 0xf8, 0x15, 0x19, 0x41, 0xd2 } };
+
+/// Interface to the rasterizer state object implemented in OpenGL
+class IRasterizerStateGL : public Diligent::IRasterizerState
+{
+public:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceFactoryOpenGL.h b/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceFactoryOpenGL.h
new file mode 100644
index 00000000..59654ce2
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceFactoryOpenGL.h
@@ -0,0 +1,106 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "RenderDevice.h"
+#include "SwapChain.h"
+
+#if defined(PLATFORM_WINDOWS) || defined(PLATFORM_WINDOWS_STORE)
+
+# define API_QUALIFIER
+
+#elif defined(PLATFORM_ANDROID)
+
+# ifdef ENGINE_DLL
+# ifdef BUILDING_DLL
+ // https://gcc.gnu.org/wiki/Visibility
+# define API_QUALIFIER __attribute__((visibility("default")))
+# else
+# define API_QUALIFIER __attribute__((visibility("default")))
+# endif
+# else
+# define API_QUALIFIER
+# endif
+
+#endif
+
+
+extern "C"
+{
+
+#if defined(ENGINE_DLL) && (defined(PLATFORM_WINDOWS) || defined(PLATFORM_WINDOWS_STORE))
+
+ typedef void (*CreateDeviceAndSwapChainGLType)( const Diligent::EngineCreationAttribs& CreationAttribs,
+ Diligent::IRenderDevice **ppDevice,
+ Diligent::IDeviceContext **ppImmediateContext,
+ const Diligent::SwapChainDesc& SwapChainDesc,
+ void *pNativeWndHandle,
+ Diligent::ISwapChain **ppSwapChain );
+
+ static void LoadGraphicsEngineOpenGL(CreateDeviceAndSwapChainGLType &CreateDeviceFunc)
+ {
+ CreateDeviceFunc = nullptr;
+ std::string LibName = "GraphicsEngineOpenGL_";
+
+#if _WIN64
+ LibName += "64";
+#else
+ LibName += "32";
+#endif
+
+#ifdef _DEBUG
+ LibName += "d";
+#else
+ LibName += "r";
+#endif
+
+ LibName += ".dll";
+ auto hModule = LoadLibraryA( LibName.c_str() );
+ if( hModule == NULL )
+ {
+ LOG_ERROR_MESSAGE( "Failed to load ", LibName, " library." );
+ return;
+ }
+
+ CreateDeviceFunc = reinterpret_cast<CreateDeviceAndSwapChainGLType>( GetProcAddress(hModule, "CreateDeviceAndSwapChainGL") );
+ if( CreateDeviceFunc == NULL )
+ {
+ LOG_ERROR_MESSAGE( "Failed to load CreateDeviceAndSwapChainGL() from ", LibName, " library." );
+ FreeLibrary( hModule );
+ return;
+ }
+ }
+
+#else
+
+ // Do not forget to call System.loadLibrary("GraphicsEngineOpenGL") in Java on Android!
+ API_QUALIFIER
+ void CreateDeviceAndSwapChainGL( const Diligent::EngineCreationAttribs& CreationAttribs,
+ Diligent::IRenderDevice **ppDevice,
+ Diligent::IDeviceContext **ppImmediateContext,
+ const Diligent::SwapChainDesc& SwapChainDesc,
+ void *pNativeWndHandle,
+ Diligent::ISwapChain **ppSwapChain );
+#endif
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGL.h b/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGL.h
new file mode 100644
index 00000000..6413c7e5
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGL.h
@@ -0,0 +1,46 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IRenderDeviceGL interface
+
+#include "RenderDevice.h"
+
+/// Namespace for the OpenGL implementation of the graphics engine
+namespace Diligent
+{
+
+// {B4B395B9-AC99-4E8A-B7E1-9DCA0D485618}
+static const Diligent::INTERFACE_ID IID_RenderDeviceGL =
+{ 0xb4b395b9, 0xac99, 0x4e8a, { 0xb7, 0xe1, 0x9d, 0xca, 0xd, 0x48, 0x56, 0x18 } };
+
+/// Interface to the render device object implemented in OpenGL
+class IRenderDeviceGL : public IRenderDevice
+{
+public:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGLES.h b/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGLES.h
new file mode 100644
index 00000000..97c82301
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGLES.h
@@ -0,0 +1,51 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IRenderDeviceGLES interface
+
+#include "RenderDevice.h"
+#include <android\native_window.h>
+#include <EGL/egl.h>
+
+namespace Diligent
+{
+
+// {F705A0D9-2023-4DE1-8B3C-C56E4CEB8DB7}
+static const Diligent::INTERFACE_ID IID_RenderDeviceGLES =
+{ 0xf705a0d9, 0x2023, 0x4de1, { 0x8b, 0x3c, 0xc5, 0x6e, 0x4c, 0xeb, 0x8d, 0xb7 } };
+
+/// Interface to the render device object implemented in OpenGLES
+class IRenderDeviceGLES : public Diligent::IRenderDevice
+{
+public:
+ virtual bool Invalidate() = 0;
+
+ virtual void Suspend() = 0;
+
+ virtual EGLint Resume( ANativeWindow* window ) = 0;
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/SamplerGL.h b/Graphics/GraphicsEngineOpenGL/interface/SamplerGL.h
new file mode 100644
index 00000000..572cd2c2
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/SamplerGL.h
@@ -0,0 +1,45 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::ISamplerGL interface
+
+#include "Sampler.h"
+
+namespace Diligent
+{
+
+// {3E9EB89E-E955-447A-9D13-92C10541F727}
+static const Diligent::INTERFACE_ID IID_SamplerGL =
+{ 0x3e9eb89e, 0xe955, 0x447a, { 0x9d, 0x13, 0x92, 0xc1, 0x5, 0x41, 0xf7, 0x27 } };
+
+/// Interface to the sampler object object implemented in OpenGL
+class ISamplerGL : public Diligent::ISampler
+{
+public:
+ //const GLObjectWrappers::GLSamplerObj& GetHandle(){ return m_GlSampler; }
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/ShaderGL.h b/Graphics/GraphicsEngineOpenGL/interface/ShaderGL.h
new file mode 100644
index 00000000..c6a5cf40
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/ShaderGL.h
@@ -0,0 +1,45 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IShaderGL interface
+
+#include "Shader.h"
+
+namespace Diligent
+{
+
+// {2FF3C191-285B-4E6C-BD0B-D084DDEA6FCC}
+static const Diligent::INTERFACE_ID IID_ShaderGL =
+{ 0x2ff3c191, 0x285b, 0x4e6c, { 0xbd, 0xb, 0xd0, 0x84, 0xdd, 0xea, 0x6f, 0xcc } };
+
+/// Interface to the shader object implemented in OpenGL
+class IShaderGL : public Diligent::IShader
+{
+public:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/SwapChainGL.h b/Graphics/GraphicsEngineOpenGL/interface/SwapChainGL.h
new file mode 100644
index 00000000..240586ac
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/SwapChainGL.h
@@ -0,0 +1,44 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::ISwapChainGL interface
+
+#include "SwapChain.h"
+
+namespace Diligent
+{
+
+// {F457BD7C-E725-4D3E-8607-A1F9BAE329EB}
+static const Diligent::INTERFACE_ID IID_SwapChainGL =
+{ 0xf457bd7c, 0xe725, 0x4d3e, { 0x86, 0x7, 0xa1, 0xf9, 0xba, 0xe3, 0x29, 0xeb } };
+
+/// Interface to the swap chain object implemented in OpenGL
+class ISwapChainGL : public Diligent::ISwapChain
+{
+public:
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/TextureGL.h b/Graphics/GraphicsEngineOpenGL/interface/TextureGL.h
new file mode 100644
index 00000000..7424b4d0
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/TextureGL.h
@@ -0,0 +1,47 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::ITextureGL interface
+
+#include "Texture.h"
+
+namespace Diligent
+{
+
+// {D7BC9FF0-28F0-4636-9732-710C204D1D63}
+static const Diligent::INTERFACE_ID IID_TextureGL =
+{ 0xd7bc9ff0, 0x28f0, 0x4636, { 0x97, 0x32, 0x71, 0xc, 0x20, 0x4d, 0x1d, 0x63 } };
+
+/// Interface to the texture object implemented in OpenGL
+class ITextureGL : public Diligent::ITexture
+{
+public:
+ //const GLObjectWrappers::GLTextureObj& GetGLHandle()const{ return m_GlTexture; }
+ //GLenum GetBindTarget()const{return m_BindTarget;}
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/TextureViewGL.h b/Graphics/GraphicsEngineOpenGL/interface/TextureViewGL.h
new file mode 100644
index 00000000..15389154
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/TextureViewGL.h
@@ -0,0 +1,46 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::ITextureViewGL interface
+
+#include "TextureView.h"
+
+namespace Diligent
+{
+
+// {15F93272-6135-414F-AB10-53FF9A5004AD}
+static const Diligent::INTERFACE_ID IID_TextureViewGL =
+{ 0x15f93272, 0x6135, 0x414f, { 0xab, 0x10, 0x53, 0xff, 0x9a, 0x50, 0x4, 0xad } };
+
+/// Interface to the texture view object implemented in OpenGL
+class ITextureViewGL : public ITextureView
+{
+public:
+ //const GLObjectWrappers::GLTextureObj& GetHandle();
+ //GLenum GetBindTarget();
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/interface/VertexDescriptionGL.h b/Graphics/GraphicsEngineOpenGL/interface/VertexDescriptionGL.h
new file mode 100644
index 00000000..1a785e9b
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/interface/VertexDescriptionGL.h
@@ -0,0 +1,45 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IVertexDescriptionGL interface
+
+#include "VertexDescription.h"
+
+namespace Diligent
+{
+
+// {4CBEE16A-7C22-4F10-8CB5-6D4E393638C7}
+static const Diligent::INTERFACE_ID IID_VertexDescriptionGL =
+{ 0x4cbee16a, 0x7c22, 0x4f10, { 0x8c, 0xb5, 0x6d, 0x4e, 0x39, 0x36, 0x38, 0xc7 } };
+
+/// Interface to the vertex description object implemented in OpenGL
+class IVertexDescriptionGL : public Diligent::IVertexDescription
+{
+public:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/BlendStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/BlendStateGLImpl.cpp
new file mode 100644
index 00000000..fd0f1734
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/BlendStateGLImpl.cpp
@@ -0,0 +1,42 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "BlendStateGLImpl.h"
+#include "RenderDeviceGLImpl.h"
+
+namespace Diligent
+{
+
+BlendStateGLImpl::BlendStateGLImpl(class IRenderDevice *pDeviceGL, const BlendStateDesc& BlendStateDesc, bool bIsDeviceInternal) :
+ TBlendStateBase(pDeviceGL, BlendStateDesc, bIsDeviceInternal)
+{
+}
+
+BlendStateGLImpl::~BlendStateGLImpl()
+{
+}
+
+IMPLEMENT_QUERY_INTERFACE( BlendStateGLImpl, IID_BlendStateGL, TBlendStateBase )
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp
new file mode 100644
index 00000000..27bce444
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp
@@ -0,0 +1,311 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "BufferGLImpl.h"
+#include "RenderDeviceGLImpl.h"
+#include "GLTypeConversions.h"
+#include "BufferViewGLImpl.h"
+#include "DeviceContextGLImpl.h"
+
+namespace Diligent
+{
+
+BufferGLImpl::BufferGLImpl(class RenderDeviceGLImpl *pDeviceGL, const BufferDesc& BuffDesc, const BufferData &BuffData /*= BufferData()*/, bool IsDeviceInternal /*= false*/) :
+ TBufferBase( pDeviceGL, BuffDesc, IsDeviceInternal ),
+ m_GlBuffer(true), // Create buffer immediately
+ m_uiMapTarget(0),
+ m_GLUsageHint(0),
+ m_bUseMapWriteDiscardBugWA(False)
+{
+ // On Intel GPUs, mapping buffer with GL_MAP_UNSYNCHRONIZED_BIT does not
+ // work as expected. To workaround this issue, use glBufferData() to
+ // orphan previous buffer storage https://www.opengl.org/wiki/Buffer_Object_Streaming
+ if( pDeviceGL->GetGPUInfo().Vendor == GPU_VENDOR::INTEL )
+ m_bUseMapWriteDiscardBugWA = True;
+
+ if( BuffDesc.Usage == USAGE_STATIC && BuffData.pData == nullptr )
+ LOG_ERROR_AND_THROW("Static buffer must be initialized with data at creation time");
+
+ // TODO: find out if it affects performance if the buffer is originally bound to one target
+ // and then bound to another (such as first to GL_ARRAY_BUFFER and then to GL_UNIFORM_BUFFER)
+ glBindBuffer(GL_ARRAY_BUFFER, m_GlBuffer);
+ VERIFY(BuffData.pData == nullptr || BuffData.DataSize >= BuffDesc.uiSizeInBytes, "Data pointer is null or data size is not consistent with buffer size" );
+ GLsizeiptr DataSize = BuffDesc.uiSizeInBytes;
+ const GLvoid *pData = nullptr;
+ if( BuffData.pData && BuffData.DataSize >= BuffDesc.uiSizeInBytes )
+ {
+ pData = BuffData.pData;
+ DataSize = BuffData.DataSize;
+ }
+ // Create and initialize a buffer object's data store
+
+ // Target must be one of GL_ARRAY_BUFFER, GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER,
+ // GL_ELEMENT_ARRAY_BUFFER, GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER, GL_TEXTURE_BUFFER,
+ // GL_TRANSFORM_FEEDBACK_BUFFER, or GL_UNIFORM_BUFFER.
+
+ // Usage must be one of GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY, GL_STATIC_DRAW,
+ // GL_STATIC_READ, GL_STATIC_COPY, GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, or GL_DYNAMIC_COPY.
+
+ //The frequency of access may be one of these:
+ //
+ //STREAM
+ // The data store contents will be modified once and used at most a few times.
+ //
+ //STATIC
+ // The data store contents will be modified once and used many times.
+ //
+ //DYNAMIC
+ // The data store contents will be modified repeatedly and used many times.
+ //
+
+ //The nature of access may be one of these:
+ //
+ //DRAW
+ // The data store contents are modified by the application, and used as the source for GL
+ // drawing and image specification commands.
+ //
+ //READ
+ // The data store contents are modified by reading data from the GL, and used to return that
+ // data when queried by the application.
+ //
+ //COPY
+ // The data store contents are modified by reading data from the GL, and used as the source
+ // for GL drawing and image specification commands.
+
+ // See also http://www.informit.com/articles/article.aspx?p=2033340&seqNum=2
+
+ m_GLUsageHint = UsageToGLUsage(BuffDesc.Usage);
+ // All buffer bind targets (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER etc.) relate to the same
+ // kind of objects. As a result they are all equivalent from a transfer point of view.
+ glBufferData(GL_ARRAY_BUFFER, DataSize, pData, m_GLUsageHint);
+ CHECK_GL_ERROR_AND_THROW("glBufferData() failed");
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+BufferGLImpl::~BufferGLImpl()
+{
+ static_cast<RenderDeviceGLImpl*>( static_cast<IRenderDevice*>( GetDevice() ) )->m_VAOCache.OnDestroyBuffer(this);
+}
+
+IMPLEMENT_QUERY_INTERFACE( BufferGLImpl, IID_BufferGL, TBufferBase )
+
+void BufferGLImpl :: UpdateData(IDeviceContext *pContext, Uint32 Offset, Uint32 Size, const PVoid pData)
+{
+ TBufferBase::UpdateData( pContext, Offset, Size, pData );
+
+ CHECK_DYNAMIC_TYPE( DeviceContextGLImpl, pContext );
+ auto *pDeviceContextGL = static_cast<DeviceContextGLImpl*>(pContext);
+
+ BufferMemoryBarrier(
+ GL_BUFFER_UPDATE_BARRIER_BIT,// Reads or writes to buffer objects via any OpenGL API functions that allow
+ // modifying their contents will reflect data written by shaders prior to the barrier.
+ // Additionally, writes via these commands issued after the barrier will wait on
+ // the completion of any shader writes to the same memory initiated prior to the barrier.
+ pDeviceContextGL->GetContextState());
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_GlBuffer);
+ // All buffer bind targets (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER etc.) relate to the same
+ // kind of objects. As a result they are all equivalent from a transfer point of view.
+ glBufferSubData(GL_ARRAY_BUFFER, Offset, Size, pData);
+ CHECK_GL_ERROR("glBufferSubData() failed");
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+
+void BufferGLImpl :: CopyData(IDeviceContext *pContext, IBuffer *pSrcBuffer, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size)
+{
+ TBufferBase::CopyData( pContext, pSrcBuffer, SrcOffset, DstOffset, Size );
+
+ CHECK_DYNAMIC_TYPE( DeviceContextGLImpl, pContext );
+ auto *pDeviceContextGL = static_cast<DeviceContextGLImpl*>(pContext);
+
+ auto *pSrcBufferGL = static_cast<BufferGLImpl*>( pSrcBuffer );
+
+ BufferMemoryBarrier(
+ GL_BUFFER_UPDATE_BARRIER_BIT,// Reads or writes to buffer objects via any OpenGL API functions that allow
+ // modifying their contents will reflect data written by shaders prior to the barrier.
+ // Additionally, writes via these commands issued after the barrier will wait on
+ // the completion of any shader writes to the same memory initiated prior to the barrier.
+ pDeviceContextGL->GetContextState());
+ pSrcBufferGL->BufferMemoryBarrier( GL_BUFFER_UPDATE_BARRIER_BIT, pDeviceContextGL->GetContextState() );
+
+ // Whilst glCopyBufferSubData() can be used to copy data between buffers bound to any two targets,
+ // the targets GL_COPY_READ_BUFFER and GL_COPY_WRITE_BUFFER are provided specifically for this purpose.
+ // Neither target is used for anything else by OpenGL, and so you can safely bind buffers to them for
+ // the purposes of copying or staging data without disturbing OpenGL state or needing to keep track of
+ // what was bound to the target before your copy.
+ glBindBuffer(GL_COPY_WRITE_BUFFER, m_GlBuffer);
+ glBindBuffer(GL_COPY_READ_BUFFER, pSrcBufferGL->m_GlBuffer);
+ glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, SrcOffset, DstOffset, Size);
+ CHECK_GL_ERROR("glCopyBufferSubData() failed");
+ glBindBuffer(GL_COPY_READ_BUFFER, 0);
+ glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
+}
+
+void BufferGLImpl :: Map(IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapFlags, PVoid &pMappedData)
+{
+ TBufferBase::Map( pContext, MapType, MapFlags, pMappedData );
+ VERIFY( m_uiMapTarget == 0, "Buffer is already mapped");
+
+ CHECK_DYNAMIC_TYPE( DeviceContextGLImpl, pContext );
+ auto *pDeviceContextGL = static_cast<DeviceContextGLImpl*>(pContext);
+
+ BufferMemoryBarrier(
+ GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT,// Access by the client to persistent mapped regions of buffer
+ // objects will reflect data written by shaders prior to the barrier.
+ // Note that this may cause additional synchronization operations.
+ pDeviceContextGL->GetContextState());
+ m_uiMapTarget = ( MapType == MAP_READ ) ? GL_COPY_READ_BUFFER : GL_COPY_WRITE_BUFFER;
+ glBindBuffer(m_uiMapTarget, m_GlBuffer);
+
+ // !!!WARNING!!! GL_MAP_UNSYNCHRONIZED_BIT is not the same thing as MAP_FLAG_DO_NOT_WAIT.
+ // If GL_MAP_UNSYNCHRONIZED_BIT flag is set, OpenGL will not attempt to synchronize operations
+ // on the buffer. This does not mean that map will fail if the buffer still in use. It is thus
+ // what WRITE_NO_OVERWRITE does
+
+ GLbitfield Access = 0;
+ switch(MapType)
+ {
+ case MAP_READ:
+ Access |= GL_MAP_READ_BIT;
+ break;
+
+ case MAP_WRITE:
+ Access |= GL_MAP_WRITE_BIT;
+ break;
+
+ case MAP_READ_WRITE:
+ Access |= GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
+ break;
+
+ case MAP_WRITE_DISCARD:
+
+ if( m_bUseMapWriteDiscardBugWA )
+ {
+ // On Intel GPU, mapping buffer with GL_MAP_UNSYNCHRONIZED_BIT does not
+ // work as expected. To workaround this issue, use glBufferData() to
+ // orphan previous buffer storage https://www.opengl.org/wiki/Buffer_Object_Streaming
+
+ // It is important to specify the exact same buffer size and usage to allow the
+ // implementation to simply reallocate storage for that buffer object under-the-hood.
+ // Since NULL is passed, if there wasn't a need for synchronization to begin with,
+ // this can be reduced to a no-op.
+ glBufferData(m_uiMapTarget, m_Desc.uiSizeInBytes, nullptr, m_GLUsageHint);
+ CHECK_GL_ERROR("glBufferData() failed");
+ Access |= GL_MAP_WRITE_BIT;
+ }
+ else
+ {
+ // Use GL_MAP_INVALIDATE_BUFFER_BIT flag to discard previous buffer contents
+
+ // If GL_MAP_INVALIDATE_BUFFER_BIT is specified, the entire contents of the buffer may
+ // be discarded and considered invalid, regardless of the specified range. Any data
+ // lying outside the mapped range of the buffer object becomes undefined,as does any
+ // data within the range but not subsequently written by the application.This flag may
+ // not be used with GL_MAP_READ_BIT.
+
+ Access |= GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_WRITE_BIT;
+ }
+ break;
+
+ case MAP_WRITE_NO_OVERWRITE:
+ // If GL_MAP_UNSYNCHRONIZED_BIT flag is set, OpenGL will not attempt to synchronize
+ // operations on the buffer.
+ Access |= GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
+ break;
+
+ default: UNEXPECTED( "Unknown map type" );
+ }
+
+ pMappedData = glMapBufferRange(m_uiMapTarget, 0, m_Desc.uiSizeInBytes, Access);
+ CHECK_GL_ERROR("glMapBufferRange() failed");
+ VERIFY( pMappedData, "Map failed" );
+ glBindBuffer(m_uiMapTarget, 0);
+}
+
+void BufferGLImpl::Unmap( IDeviceContext *pContext )
+{
+ TBufferBase::Unmap(pContext);
+
+ glBindBuffer(m_uiMapTarget, m_GlBuffer);
+ auto Result = glUnmapBuffer(m_uiMapTarget);
+ // glUnmapBuffer() returns TRUE unless data values in the buffer’s data store have
+ // become corrupted during the period that the buffer was mapped. Such corruption
+ // can be the result of a screen resolution change or other window system - dependent
+ // event that causes system heaps such as those for high - performance graphics memory
+ // to be discarded. GL implementations must guarantee that such corruption can
+ // occur only during the periods that a buffer’s data store is mapped. If such corruption
+ // has occurred, glUnmapBuffer() returns FALSE, and the contents of the buffer’s
+ // data store become undefined.
+ VERIFY( Result != GL_FALSE, "Failed to unmap buffer. The data may have been corrupted" );
+ glBindBuffer(m_uiMapTarget, 0);
+ m_uiMapTarget = 0;
+}
+
+void BufferGLImpl::BufferMemoryBarrier( Uint32 RequiredBarriers, GLContextState &GLContextState )
+{
+ const Uint32 BufferBarriers =
+ GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT |
+ GL_ELEMENT_ARRAY_BARRIER_BIT |
+ GL_UNIFORM_BARRIER_BIT |
+ GL_COMMAND_BARRIER_BIT |
+ GL_BUFFER_UPDATE_BARRIER_BIT |
+ GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT |
+ GL_SHADER_STORAGE_BARRIER_BIT |
+ GL_TEXTURE_FETCH_BARRIER_BIT;
+ VERIFY( (RequiredBarriers & BufferBarriers) !=0, "At least one buffer memory barrier flag should be set" );
+ VERIFY( (RequiredBarriers & ~BufferBarriers) == 0, "Inappropriate buffer memory barrier flag" );
+
+ GLContextState.EnsureMemoryBarrier( RequiredBarriers, this );
+}
+
+void BufferGLImpl::CreateViewInternal( const BufferViewDesc &OrigViewDesc, class IBufferView **ppView, bool bIsDefaultView )
+{
+ VERIFY( ppView != nullptr, "Buffer view pointer address is null" );
+ if( !ppView )return;
+ VERIFY( *ppView == nullptr, "Overwriting reference to existing object may cause memory leaks" );
+
+ *ppView = nullptr;
+
+ try
+ {
+ auto ViewDesc = OrigViewDesc;
+ CorrectBufferViewDesc( ViewDesc );
+
+ auto pContext = ValidatedCast<RenderDeviceGLImpl>( GetDevice() )->GetImmediateContext();
+ VERIFY( pContext, "Immediate context has been released" );
+ *ppView = new BufferViewGLImpl( GetDevice(), pContext, ViewDesc, this, bIsDefaultView );
+
+ if( !bIsDefaultView )
+ (*ppView)->AddRef();
+ }
+ catch( const std::runtime_error & )
+ {
+ const auto *ViewTypeName = GetBufferViewTypeLiteralName(OrigViewDesc.ViewType);
+ LOG_ERROR("Failed to create view \"", OrigViewDesc.Name ? OrigViewDesc.Name : "", "\" (", ViewTypeName, ") for buffer \"", m_Desc.Name ? m_Desc.Name : "", "\"" )
+ }
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp
new file mode 100644
index 00000000..6c185749
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp
@@ -0,0 +1,60 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "RenderDeviceGLImpl.h"
+#include "DeviceContextGLImpl.h"
+#include "BufferViewGLImpl.h"
+#include "BufferGLImpl.h"
+#include "GLTypeConversions.h"
+
+namespace Diligent
+{
+ BufferViewGLImpl::BufferViewGLImpl( IRenderDevice *pDevice,
+ IDeviceContext *pContext,
+ const BufferViewDesc& ViewDesc,
+ BufferGLImpl* pBuffer,
+ bool bIsDefaultView) :
+ TBuffViewBase(pDevice, ViewDesc, pBuffer, bIsDefaultView ),
+ m_GLTexBuffer(false)
+ {
+ if( ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE )
+ {
+ auto *pContextGL = ValidatedCast<DeviceContextGLImpl>(pContext);
+ auto &ContextState = pContextGL->GetContextState();
+
+ m_GLTexBuffer.Create();
+ ContextState.BindTexture(-1, GL_TEXTURE_BUFFER, m_GLTexBuffer );
+
+ const auto &BuffFmt = pBuffer->GetDesc().Format;
+ auto GLFormat = TypeToGLTexFormat( BuffFmt.ValueType, BuffFmt.NumComponents, BuffFmt.IsNormalized );
+ glTexBuffer( GL_TEXTURE_BUFFER, GLFormat, pBuffer->GetGLBufferHandle() );
+ CHECK_GL_ERROR_AND_THROW( "Failed to create texture buffer" );
+
+ ContextState.BindTexture(-1, GL_TEXTURE_BUFFER, GLObjectWrappers::GLTextureObj(false) );
+ }
+ }
+
+ IMPLEMENT_QUERY_INTERFACE( BufferViewGLImpl, IID_BufferViewGL, TBuffViewBase )
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/DLLMain.cpp b/Graphics/GraphicsEngineOpenGL/src/DLLMain.cpp
new file mode 100644
index 00000000..373d1570
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/DLLMain.cpp
@@ -0,0 +1,49 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+BOOL APIENTRY DllMain(HANDLE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved)
+{
+ switch( ul_reason_for_call )
+ {
+ case DLL_PROCESS_ATTACH:
+ #if defined(_DEBUG) || defined(DEBUG)
+ _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
+ #endif
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return TRUE;
+} \ No newline at end of file
diff --git a/Graphics/GraphicsEngineOpenGL/src/DSStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DSStateGLImpl.cpp
new file mode 100644
index 00000000..1b9929b6
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/DSStateGLImpl.cpp
@@ -0,0 +1,43 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "DSStateGLImpl.h"
+#include "RenderDeviceGLImpl.h"
+
+namespace Diligent
+{
+
+DSStateGLImpl::DSStateGLImpl(class IRenderDevice *pDeviceGL, const DepthStencilStateDesc& DepthStencilStateDesc, bool bIsDeviceInternal) :
+ TDSStateBase(pDeviceGL, DepthStencilStateDesc, bIsDeviceInternal)
+{
+}
+
+DSStateGLImpl::~DSStateGLImpl()
+{
+
+}
+
+IMPLEMENT_QUERY_INTERFACE( DSStateGLImpl, IID_DepthStencilStateGL, TDSStateBase )
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
new file mode 100644
index 00000000..832a5eb8
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
@@ -0,0 +1,889 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "DeviceContextGLImpl.h"
+#include "RenderDeviceGLImpl.h"
+#include "GLTypeConversions.h"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "BufferGLImpl.h"
+#include "VertexDescGLImpl.h"
+#include "ShaderGLImpl.h"
+#include "VAOCache.h"
+#include "ProgramPipelineCache.h"
+#include "Texture1D_OGL.h"
+#include "Texture1DArray_OGL.h"
+#include "Texture2D_OGL.h"
+#include "Texture2DArray_OGL.h"
+#include "Texture3D_OGL.h"
+#include "SamplerGLImpl.h"
+#include "GraphicsUtilities.h"
+#include "BufferViewGLImpl.h"
+#include "DSStateGLImpl.h"
+#include "BlendStateGLImpl.h"
+#include "RasterizerStateGLImpl.h"
+
+using namespace std;
+
+namespace Diligent
+{
+ DeviceContextGLImpl::DeviceContextGLImpl( class RenderDeviceGLImpl *pDeviceGL ) :
+ TDeviceContextBase(pDeviceGL),
+ m_ContextState(pDeviceGL)
+ {
+ m_BoundWritableTextures.reserve( 16 );
+ m_BoundWritableBuffers.reserve( 16 );
+
+ // When GL_FRAMEBUFFER_SRGB is enabled, and if the destination image is in the sRGB colorspace
+ // then OpenGL will assume the shader's output is in the linear RGB colorspace. It will therefore
+ // convert the output from linear RGB to sRGB.
+ // Any writes to images that are not in the sRGB format should not be affected.
+ // Thus this setting should be just set once and left that way
+ glEnable(GL_FRAMEBUFFER_SRGB);
+ if( glGetError() != GL_NO_ERROR )
+ LOG_ERROR_MESSAGE("Failed to enable SRGB framebuffers");
+ }
+
+ IMPLEMENT_QUERY_INTERFACE( DeviceContextGLImpl, IID_DeviceContextGL, TDeviceContextBase )
+
+
+ void DeviceContextGLImpl::SetShaders( IShader **ppShaders, Uint32 NumShadersToSet )
+ {
+ TDeviceContextBase::SetShaders( ppShaders, NumShadersToSet );
+
+ }
+
+ void DeviceContextGLImpl::BindShaderResources( IResourceMapping *pResourceMapping, Uint32 Flags )
+ {
+ TDeviceContextBase::BindShaderResources( pResourceMapping, Flags );
+ if( m_pDevice->GetDeviceCaps().bSeparableProgramSupported )
+ {
+ for( auto it = m_pBoundShaders.begin(); it != m_pBoundShaders.end(); ++it )
+ {
+ (*it)->BindResources( pResourceMapping, Flags );
+ }
+ }
+ else
+ {
+ auto *pRenderDeviceGL = ValidatedCast<RenderDeviceGLImpl>(m_pDevice.RawPtr());
+ auto &PipelineCache = pRenderDeviceGL->m_PipelineCache;
+ auto &PipelineOrProg = PipelineCache.GetProgramPipeline( m_pBoundShaders.data(), (Uint32)m_pBoundShaders.size() );
+ if( PipelineOrProg.Program )
+ PipelineOrProg.Program.BindResources( pResourceMapping, Flags );
+ }
+ }
+
+ void DeviceContextGLImpl::SetVertexBuffers( Uint32 StartSlot, Uint32 NumBuffersSet, IBuffer **ppBuffers, Uint32 *pStrides, Uint32 *pOffsets, Uint32 Flags )
+ {
+ TDeviceContextBase::SetVertexBuffers( StartSlot, NumBuffersSet, ppBuffers, pStrides, pOffsets, Flags );
+
+ }
+
+ void DeviceContextGLImpl::ClearState()
+ {
+ TDeviceContextBase::ClearState();
+
+ }
+
+ void DeviceContextGLImpl::SetVertexDescription( IVertexDescription *pVertexDesc )
+ {
+ TDeviceContextBase::SetVertexDescription( pVertexDesc );
+ }
+
+ void DeviceContextGLImpl::SetIndexBuffer( IBuffer *pIndexBuffer, Uint32 ByteOffset )
+ {
+ TDeviceContextBase::SetIndexBuffer( pIndexBuffer, ByteOffset );
+ }
+
+ void DeviceContextGLImpl::SetDepthStencilState( IDepthStencilState *pDepthStencilState, Uint32 StencilRef )
+ {
+ if( TDeviceContextBase::SetDepthStencilState( pDepthStencilState, StencilRef ) )
+ {
+ CHECK_DYNAMIC_TYPE( DSStateGLImpl, pDepthStencilState );
+ auto *pDSSGL = static_cast<DSStateGLImpl*>(pDepthStencilState);
+ const auto &DSSDesc = pDepthStencilState->GetDesc();
+
+ m_ContextState.EnableDepthTest( DSSDesc.DepthEnable );
+ m_ContextState.EnableDepthWrites( DSSDesc.DepthWriteEnable );
+ m_ContextState.SetDepthFunc( DSSDesc.DepthFunc );
+
+ m_ContextState.EnableStencilTest( DSSDesc.StencilEnable );
+
+ m_ContextState.SetStencilWriteMask( DSSDesc.StencilWriteMask );
+
+ {
+ const auto &FrontFace = DSSDesc.FrontFace;
+ m_ContextState.SetStencilFunc( GL_FRONT, FrontFace.StencilFunc, StencilRef, DSSDesc.StencilReadMask );
+ m_ContextState.SetStencilOp( GL_FRONT, FrontFace.StencilFailOp, FrontFace.StencilDepthFailOp, FrontFace.StencilPassOp );
+ }
+
+ {
+ const auto &BackFace = DSSDesc.BackFace;
+ m_ContextState.SetStencilFunc( GL_BACK, BackFace.StencilFunc, StencilRef, DSSDesc.StencilReadMask );
+ m_ContextState.SetStencilOp( GL_BACK, BackFace.StencilFailOp, BackFace.StencilDepthFailOp, BackFace.StencilPassOp );
+ }
+ }
+ }
+
+ void DeviceContextGLImpl::SetRasterizerState( IRasterizerState *pRasterizerState )
+ {
+ if( TDeviceContextBase::SetRasterizerState( pRasterizerState ) )
+ {
+ CHECK_DYNAMIC_TYPE( RasterizerStateGLImpl, pRasterizerState );
+ auto *pRSGL = static_cast<RasterizerStateGLImpl*>(pRasterizerState);
+ const auto &RSDesc = pRasterizerState->GetDesc();
+
+ m_ContextState.SetFillMode(RSDesc.FillMode);
+ m_ContextState.SetCullMode(RSDesc.CullMode);
+ m_ContextState.SetFrontFace(RSDesc.FrontCounterClockwise);
+ m_ContextState.SetDepthBias( static_cast<Float32>( RSDesc.DepthBias ), RSDesc.SlopeScaledDepthBias );
+ if( RSDesc.DepthBiasClamp != 0 )
+ LOG_WARNING_MESSAGE( "Depth bias clamp is not supported on OpenGL" );
+ m_ContextState.SetDepthClamp( RSDesc.DepthClipEnable );
+ m_ContextState.EnableScissorTest( RSDesc.ScissorEnable );
+ if( RSDesc.AntialiasedLineEnable )
+ LOG_WARNING_MESSAGE( "Line antialiasing is not supported on OpenGL" );
+ }
+ }
+
+
+ void DeviceContextGLImpl::SetBlendState( IBlendState *pBS, const float* pBlendFactors, Uint32 SampleMask )
+ {
+ if( TDeviceContextBase::SetBlendState( pBS, pBlendFactors, SampleMask ) )
+ {
+ CHECK_DYNAMIC_TYPE( BlendStateGLImpl, pBS );
+ auto *pBSGL = static_cast<BlendStateGLImpl*>(pBS);
+ const auto BSDsc = pBS->GetDesc();
+ m_ContextState.SetBlendState(BSDsc, m_BlendFactors, SampleMask);
+ }
+ }
+
+ void DeviceContextGLImpl::SetViewports( Uint32 NumViewports, const Viewport *pViewports, Uint32 RTWidth, Uint32 RTHeight )
+ {
+ TDeviceContextBase::SetViewports( NumViewports, pViewports, RTWidth, RTHeight );
+
+ VERIFY( NumViewports == m_Viewports.size(), "Unexpected number of viewports" );
+ if( NumViewports == 1 )
+ {
+ const auto &vp = m_Viewports[0];
+ // Note that OpenGL and DirectX use different origin of
+ // the viewport in window coordinates:
+ //
+ // DirectX (0,0)
+ // \ ____________
+ // | |
+ // | |
+ // | |
+ // | |
+ // |____________|
+ // /
+ // OpenGL (0,0)
+ //
+ float BottomLeftY = static_cast<float>(RTHeight) - (vp.TopLeftY + vp.Height);
+ float BottomLeftX = vp.TopLeftX;
+
+ Int32 x = static_cast<int>(BottomLeftX);
+ Int32 y = static_cast<int>(BottomLeftY);
+ Int32 w = static_cast<int>(vp.Width);
+ Int32 h = static_cast<int>(vp.Height);
+ if( static_cast<float>(x) == BottomLeftX &&
+ static_cast<float>(y) == BottomLeftY &&
+ static_cast<float>(w) == vp.Width &&
+ static_cast<float>(h) == vp.Height )
+ {
+ glViewport( x, y, w, h );
+ }
+ else
+ {
+ glViewportIndexedf( 0, BottomLeftX, BottomLeftY, vp.Width, vp.Height );
+ }
+ CHECK_GL_ERROR( "Failed to set viewport" );
+
+ glDepthRangef( vp.MinDepth, vp.MaxDepth );
+ CHECK_GL_ERROR( "Failed to set depth range" );
+ }
+ else
+ {
+ for( Uint32 i = 0; i < NumViewports; ++i )
+ {
+ const auto &vp = m_Viewports[i];
+ float BottomLeftY = static_cast<float>(RTHeight) - (vp.TopLeftY + vp.Height);
+ float BottomLeftX = vp.TopLeftX;
+ glViewportIndexedf( i, BottomLeftX, BottomLeftY, vp.Width, vp.Height );
+ CHECK_GL_ERROR( "Failed to set viewport #", i );
+ glDepthRangef( vp.MinDepth, vp.MaxDepth );
+ CHECK_GL_ERROR( "Failed to set depth range for viewport #", i );
+ }
+ }
+ }
+
+ void DeviceContextGLImpl::SetScissorRects( Uint32 NumRects, const Rect *pRects, Uint32 RTWidth, Uint32 RTHeight )
+ {
+ TDeviceContextBase::SetScissorRects(NumRects, pRects, RTWidth, RTHeight);
+
+ VERIFY( NumRects == m_ScissorRects.size(), "Unexpected number of scissor rects" );
+ if( NumRects == 1 )
+ {
+ const auto &Rect = m_ScissorRects[0];
+ // Note that OpenGL and DirectX use different origin
+ // of the viewport in window coordinates:
+ //
+ // DirectX (0,0)
+ // \ ____________
+ // | |
+ // | |
+ // | |
+ // | |
+ // |____________|
+ // /
+ // OpenGL (0,0)
+ //
+ auto glBottom = RTHeight - Rect.bottom;
+
+ auto width = Rect.right - Rect.left;
+ auto height = Rect.bottom - Rect.top;
+ glScissor( Rect.left, glBottom, width, height );
+ CHECK_GL_ERROR( "Failed to set scissor rect" );
+ }
+ else
+ {
+ for( Uint32 sr = 0; sr < NumRects; ++sr )
+ {
+ const auto &Rect = m_ScissorRects[sr];
+ auto glBottom = RTHeight - Rect.bottom;
+ auto width = Rect.right - Rect.left;
+ auto height = Rect.bottom - Rect.top;
+ glScissorIndexed(sr, Rect.left, glBottom, width, height );
+ CHECK_GL_ERROR( "Failed to set scissor rect #", sr );
+ }
+ }
+ }
+
+ void DeviceContextGLImpl::RebindRenderTargets()
+ {
+ Uint32 NumRenderTargets = static_cast<Uint32>( m_pBoundRenderTargets.size() );
+ VERIFY( NumRenderTargets < MaxRenderTargets, "Too many render targets (", NumRenderTargets, ") are being set" );
+
+ NumRenderTargets = std::min( NumRenderTargets, MaxRenderTargets );
+ ITextureView *pBoundRTVs[MaxRenderTargets] = {};
+ for( Uint32 rt = 0; rt < NumRenderTargets; ++rt )
+ pBoundRTVs[rt] = m_pBoundRenderTargets[rt];
+
+ auto *pRenderDeviceGL = ValidatedCast<RenderDeviceGLImpl>(m_pDevice.RawPtr());
+ auto &FBOCache = pRenderDeviceGL->m_FBOCache;
+ const auto& FBO = FBOCache.GetFBO( NumRenderTargets, pBoundRTVs, m_pBoundDepthStencil, m_ContextState );
+ // Even though the write mask only applies to writes to a framebuffer, the mask state is NOT
+ // Framebuffer state. So it is NOT part of a Framebuffer Object or the Default Framebuffer.
+ // Binding a new framebuffer will NOT affect the mask.
+ m_ContextState.BindFBO( FBO );
+
+ // Set the viewport to match the render target size
+ SetViewports(1, nullptr, 0, 0);
+ }
+
+ void DeviceContextGLImpl::SetRenderTargets( Uint32 NumRenderTargets, ITextureView *ppRenderTargets[], ITextureView *pDepthStencil )
+ {
+ if( TDeviceContextBase::SetRenderTargets( NumRenderTargets, ppRenderTargets, pDepthStencil ) )
+ RebindRenderTargets();
+ }
+
+ void DeviceContextGLImpl::BindProgramResources( Uint32 &NewMemoryBarriers )
+ {
+ auto *pRenderDeviceGL = ValidatedCast<RenderDeviceGLImpl>(m_pDevice.RawPtr());
+ auto &PipelineCache = pRenderDeviceGL->m_PipelineCache;
+ auto &PipelineOrProg = PipelineCache.GetProgramPipeline( m_pBoundShaders.data(), (Uint32)m_pBoundShaders.size() );
+
+ const auto &DeviceCaps = pRenderDeviceGL->GetDeviceCaps();
+ GLuint Prog = PipelineOrProg.Program;
+ GLuint Pipeline = PipelineOrProg.Pipeline;
+ VERIFY( Prog ^ Pipeline, "Only one of program or pipeline can be specified" );
+ if( !(Prog || Pipeline) )
+ {
+ LOG_ERROR_MESSAGE( "No program/program pipeline is set for the draw call" )
+ return;
+ }
+ auto ProgramPipelineSupported = DeviceCaps.bSeparableProgramSupported;
+
+ // WARNING: glUseProgram() overrides glBindProgramPipeline(). That is, if you have a program in use and
+ // a program pipeline bound, all rendering will use the program that is in use, not the pipeline programs!!!
+ // So make sure that glUseProgram(0) has been called if pipeline is in use
+ m_ContextState.SetProgram( PipelineOrProg.Program );
+ if( ProgramPipelineSupported )
+ m_ContextState.SetPipeline( PipelineOrProg.Pipeline );
+
+ size_t NumPrograms = ProgramPipelineSupported ? m_pBoundShaders.size() : 1;
+ GLuint UniformBuffBindPoint = 0;
+ GLuint TextureIndex = 0;
+ m_BoundWritableTextures.clear();
+ m_BoundWritableBuffers.clear();
+ for( size_t ProgNum = 0; ProgNum < NumPrograms; ++ProgNum )
+ {
+ auto *pShaderGL = static_cast<ShaderGLImpl*>(m_pBoundShaders[ProgNum].RawPtr());
+ auto &GLProgramObj = ProgramPipelineSupported ? pShaderGL->m_GlProgObj : PipelineOrProg.Program;
+
+#ifdef VERIFY_RESOURCE_BINDINGS
+ GLProgramObj.dbgVerifyResourceBindings();
+#endif
+
+ GLuint GLProgID = GLProgramObj;
+ auto &UniformBlocks = GLProgramObj.GetUniformBlocks();
+ for( auto it = UniformBlocks.begin(); it != UniformBlocks.end(); ++it )
+ {
+ auto& pResource = it->pResource;
+ if( pResource )
+ {
+ CHECK_DYNAMIC_TYPE( BufferGLImpl, pResource.RawPtr() );
+ auto *pBufferOGL = static_cast<BufferGLImpl*>(pResource.RawPtr());
+ pBufferOGL->BufferMemoryBarrier(
+ GL_UNIFORM_BARRIER_BIT,// Shader uniforms sourced from buffer objects after the barrier
+ // will reflect data written by shaders prior to the barrier
+ m_ContextState);
+
+ glBindBufferBase( GL_UNIFORM_BUFFER, UniformBuffBindPoint, pBufferOGL->m_GlBuffer );
+ CHECK_GL_ERROR( "Failed to bind uniform buffer" );
+ //glBindBufferRange(GL_UNIFORM_BUFFER, it->Index, pBufferOGL->m_GlBuffer, 0, pBufferOGL->GetDesc().uiSizeInBytes);
+
+ glUniformBlockBinding( GLProgID, it->Index, UniformBuffBindPoint );
+ CHECK_GL_ERROR( "glUniformBlockBinding() failed" );
+
+ ++UniformBuffBindPoint;
+ }
+ else
+ {
+#define LOG_MISSING_BINDING(VarType, VarName) LOG_ERROR_MESSAGE( "No ", VarType, " is bound to \"", VarName, "\" variable in shader \"", pShaderGL->GetDesc().Name, "\"" );
+ LOG_MISSING_BINDING("uniform buffer", it->Name)
+ }
+ }
+
+ auto &Samplers = GLProgramObj.GetSamplers();
+ for( auto it = Samplers.begin(); it != Samplers.end(); ++it )
+ {
+ auto &pResource = it->pResource;
+ if( pResource )
+ {
+ if( it->Type == GL_SAMPLER_BUFFER ||
+ it->Type == GL_INT_SAMPLER_BUFFER ||
+ it->Type == GL_UNSIGNED_INT_SAMPLER_BUFFER )
+ {
+ CHECK_DYNAMIC_TYPE( BufferViewGLImpl, pResource.RawPtr() );
+ auto *pBufViewOGL = static_cast<BufferViewGLImpl*>(pResource.RawPtr());
+ auto *pBuffer = pBufViewOGL->GetBuffer();
+
+ m_ContextState.BindTexture( TextureIndex, GL_TEXTURE_BUFFER, pBufViewOGL->GetTexBufferHandle() );
+ m_ContextState.BindSampler( TextureIndex, GLObjectWrappers::GLSamplerObj(false) ); // Use default texture sampling parameters
+
+ CHECK_DYNAMIC_TYPE( BufferGLImpl, pBuffer );
+ static_cast<BufferGLImpl*>(pBuffer)->BufferMemoryBarrier(
+ GL_TEXTURE_FETCH_BARRIER_BIT, // Texture fetches from shaders, including fetches from buffer object
+ // memory via buffer textures, after the barrier will reflect data
+ // written by shaders prior to the barrier
+ m_ContextState);
+ }
+ else
+ {
+ CHECK_DYNAMIC_TYPE( TextureViewGLImpl, pResource.RawPtr() );
+ auto *pTexViewOGL = static_cast<TextureViewGLImpl*>(pResource.RawPtr());
+ m_ContextState.BindTexture( TextureIndex, pTexViewOGL->GetBindTarget(), pTexViewOGL->GetHandle() );
+
+ auto *pTexture = pTexViewOGL->GetTexture();
+ CHECK_DYNAMIC_TYPE( TextureBaseGL, pTexture );
+ static_cast<TextureBaseGL*>(pTexture)->TextureMemoryBarrier(
+ GL_TEXTURE_FETCH_BARRIER_BIT, // Texture fetches from shaders, including fetches from buffer object
+ // memory via buffer textures, after the barrier will reflect data
+ // written by shaders prior to the barrier
+ m_ContextState);
+
+ auto pSampler = pTexViewOGL->GetSampler();
+ if( pSampler )
+ {
+ auto *pSamplerGL = ValidatedCast<SamplerGLImpl>( pSampler );
+ m_ContextState.BindSampler( TextureIndex, pSamplerGL->GetHandle() );
+ }
+ }
+
+ // Texture is now bound to texture slot TextureIndex.
+ // We now need to set the program uniform to use that slot
+ if( ProgramPipelineSupported )
+ {
+ // glProgramUniform1i does not require program to be bound to the pipeline
+ glProgramUniform1i( GLProgramObj, it->Location, TextureIndex );
+ }
+ else
+ {
+ // glUniform1i requires program to be bound to the pipeline
+ glUniform1i( it->Location, TextureIndex );
+ }
+ CHECK_GL_ERROR( "Failed to bind sampler uniform to texture slot" );
+
+ ++TextureIndex;
+ }
+ else
+ {
+ LOG_MISSING_BINDING("texture sampler", it->Name)
+ }
+ }
+
+ auto &Images = GLProgramObj.GetImages();
+ for( auto it = Images.begin(); it != Images.end(); ++it )
+ {
+ auto &pResource = it->pResource;
+ if( pResource )
+ {
+ CHECK_DYNAMIC_TYPE( TextureViewGLImpl, pResource.RawPtr() );
+ auto *pTexViewOGL = static_cast<TextureViewGLImpl*>(pResource.RawPtr());
+ const auto &ViewDesc = pTexViewOGL->GetDesc();
+
+ if( ViewDesc.AccessFlags & UAV_ACCESS_FLAG_WRITE )
+ {
+ auto *pTex = pTexViewOGL->GetTexture();
+ CHECK_DYNAMIC_TYPE( TextureBaseGL, pTex );
+ auto *pTexGL = static_cast<TextureBaseGL*>(pTex);
+
+ pTexGL->TextureMemoryBarrier(
+ GL_SHADER_IMAGE_ACCESS_BARRIER_BIT,// Memory accesses using shader image load, store, and atomic built-in
+ // functions issued after the barrier will reflect data written by shaders
+ // prior to the barrier. Additionally, image stores and atomics issued after
+ // the barrier will not execute until all memory accesses (e.g., loads,
+ // stores, texture fetches, vertex fetches) initiated prior to the barrier
+ // complete.
+ m_ContextState);
+ // We cannot set pending memory barriers here, because
+ // if some texture is bound twice, the logic will fail
+ m_BoundWritableTextures.push_back( pTexGL );
+ }
+
+#ifdef _DEBUG
+ // Check that the texure being bound has immutable storage
+ {
+ m_ContextState.BindTexture( -1, pTexViewOGL->GetBindTarget(), pTexViewOGL->GetHandle() );
+ GLint IsImmutable = 0;
+ glGetTexParameteriv( pTexViewOGL->GetBindTarget(), GL_TEXTURE_IMMUTABLE_FORMAT, &IsImmutable );
+ CHECK_GL_ERROR( "glGetTexParameteriv() failed" );
+ VERIFY( IsImmutable, "Only immutable textures can be bound to pipeline using glBindImageTexture()" );
+ m_ContextState.BindTexture( -1, pTexViewOGL->GetBindTarget(), GLObjectWrappers::GLTextureObj(false) );
+ }
+#endif
+ auto GlTexFormat = TexFormatToGLInternalTexFormat( ViewDesc.Format );
+ // Note that if a format qulifier is specified in the shader, the format
+ // must match it
+
+ GLboolean Layered = ViewDesc.NumArraySlices > 1 && ViewDesc.FirstArraySlice == 0;
+ // If "layered" is TRUE, the entire Mip level is bound. Layer parameter is ignored in this
+ // case. If "layered" is FALSE, only the single layer identified by "layer" will
+ // be bound. When "layered" is FALSE, the single bound layer is treated as a 2D texture.
+ GLint Layer = ViewDesc.FirstArraySlice;
+
+ auto GLAccess = AccessFlags2GLAccess( ViewDesc.AccessFlags );
+ // WARNING: Texture being bound to the image unit must be complete
+ // That means that if an integer texture is being bound, its
+ // GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER must be NEAREST,
+ // otherwise it will be incomplete
+ m_ContextState.BindImage( it->BindingPoint, pTexViewOGL, ViewDesc.MostDetailedMip, Layered, Layer, GLAccess, GlTexFormat );
+ }
+ else
+ {
+ LOG_MISSING_BINDING("image", it->Name)
+ }
+ }
+
+ auto &StorageBlocks = GLProgramObj.GetStorageBlocks();
+ for( auto it = StorageBlocks.begin(); it != StorageBlocks.end(); ++it )
+ {
+ auto &pResource = it->pResource;
+ if( pResource )
+ {
+ CHECK_DYNAMIC_TYPE( BufferViewGLImpl, pResource.RawPtr() );
+ auto *pBufferViewOGL = static_cast<BufferViewGLImpl*>(pResource.RawPtr());
+ const auto &ViewDesc = pBufferViewOGL->GetDesc();
+ VERIFY( ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Incorrect buffer view type" );
+
+ auto *pBuffer = pBufferViewOGL->GetBuffer();
+ CHECK_DYNAMIC_TYPE( BufferGLImpl, pBuffer );
+ auto *pBufferOGL = static_cast<BufferGLImpl*>(pBuffer);
+
+ pBufferOGL->BufferMemoryBarrier(
+ GL_SHADER_STORAGE_BARRIER_BIT,// Accesses to shader storage blocks after the barrier
+ // will reflect writes prior to the barrier
+ m_ContextState);
+
+ glBindBufferRange( GL_SHADER_STORAGE_BUFFER, it->Binding, pBufferOGL->m_GlBuffer, ViewDesc.ByteOffset, ViewDesc.ByteWidth );
+ CHECK_GL_ERROR( "Failed to bind shader storage buffer" );
+
+ m_BoundWritableBuffers.push_back( pBufferOGL );
+ }
+ else
+ {
+ LOG_MISSING_BINDING("shader storage block", it->Name )
+ }
+ }
+ }
+
+ // Go through the list of textures bound as AUVs and set the required memory barriers
+ for( auto pWritableTex = m_BoundWritableTextures.begin(); pWritableTex != m_BoundWritableTextures.end(); ++pWritableTex )
+ {
+ Uint32 TextureMemBarriers =
+ GL_TEXTURE_UPDATE_BARRIER_BIT // Writes to a texture via glTex(Sub)Image*, glCopyTex(Sub)Image*,
+ // glClearTex*Image, glCompressedTex(Sub)Image*, and reads via
+ // glGetTexImage() after the barrier will reflect data written by
+ // shaders prior to the barrier
+
+ | GL_TEXTURE_FETCH_BARRIER_BIT // Texture fetches from shaders, including fetches from buffer object
+ // memory via buffer textures, after the barrier will reflect data
+ // written by shaders prior to the barrier
+
+ | GL_PIXEL_BUFFER_BARRIER_BIT // Reads and writes of buffer objects via the GL_PIXEL_PACK_BUFFER and
+ // GL_PIXEL_UNPACK_BUFFER bidnings after the barrier will reflect data
+ // written by shaders prior to the barrier
+
+ | GL_FRAMEBUFFER_BARRIER_BIT // Reads and writes via framebuffer object attachments after the
+ // barrier will reflect data written by shaders prior to the barrier.
+ // Additionally, framebuffer writes issued after the barrier will wait
+ // on the completion of all shader writes issued prior to the barrier.
+
+ | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT;
+
+ NewMemoryBarriers |= TextureMemBarriers;
+
+ // Set new required barriers for the time when texture is used next time
+ (*pWritableTex)->SetPendingMemoryBarriers( TextureMemBarriers );
+ }
+
+ for( auto pWritableBuff = m_BoundWritableBuffers.begin(); pWritableBuff != m_BoundWritableBuffers.end(); ++pWritableBuff )
+ {
+ Uint32 BufferMemoryBarriers =
+ GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT |
+ GL_ELEMENT_ARRAY_BARRIER_BIT |
+ GL_UNIFORM_BARRIER_BIT |
+ GL_COMMAND_BARRIER_BIT |
+ GL_BUFFER_UPDATE_BARRIER_BIT |
+ GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT |
+ GL_SHADER_STORAGE_BARRIER_BIT |
+ GL_TEXTURE_FETCH_BARRIER_BIT;
+
+ NewMemoryBarriers |= BufferMemoryBarriers;
+ // Set new required barriers for the time when buffer is used next time
+ (*pWritableBuff)->SetPendingMemoryBarriers( BufferMemoryBarriers );
+ }
+ }
+
+ void DeviceContextGLImpl::Draw( DrawAttribs &DrawAttribs )
+ {
+ if( DrawAttribs.Topology == PRIMITIVE_TOPOLOGY_UNDEFINED )
+ {
+ LOG_ERROR_MESSAGE("Primitive topology is undefined");
+ return;
+ }
+
+ RefCntWeakPtr<IBuffer> pIndexBuffer;
+ if( DrawAttribs.IsIndexed )
+ pIndexBuffer = m_pIndexBuffer;
+
+ // Obtain strong reference to the vertex description object and index buffer
+ auto &spVertexDesc = m_pVertexDesc;
+ auto *pRenderDeviceGL = ValidatedCast<RenderDeviceGLImpl>(m_pDevice.RawPtr());
+ if( spVertexDesc )
+ {
+ auto &VAOCache = pRenderDeviceGL->m_VAOCache;
+ auto spIndexBuff = pIndexBuffer.Lock();
+ const auto& VAO = VAOCache.GetVAO( *spVertexDesc, spIndexBuff, m_VertexStreams, m_ContextState );
+ m_ContextState.BindVAO( VAO );
+ }
+ else
+ {
+ // Draw command will fail if no VAO is bound. If no vertex description is set
+ // (which is the case if, for instance, the command only inputs VertexID),
+ // use empty VAO
+ m_ContextState.BindVAO( pRenderDeviceGL->m_EmptyVAO );
+ }
+
+ auto GlTopology = PrimitiveTopologyToGLTopology( DrawAttribs.Topology );
+ GLenum IndexType = 0;
+ Uint32 FirstIndexByteOffset = 0;
+ if( DrawAttribs.IsIndexed )
+ {
+ IndexType = TypeToGLType( DrawAttribs.IndexType );
+ VERIFY( IndexType == GL_UNSIGNED_BYTE || IndexType == GL_UNSIGNED_SHORT || IndexType == GL_UNSIGNED_INT,
+ "Unsupported index type" );
+ VERIFY( m_pIndexBuffer, "Index Buffer is not bound to the pipeline" );
+ FirstIndexByteOffset = static_cast<Uint32>(GetValueSize( DrawAttribs.IndexType )) * DrawAttribs.FirstIndexLocation + m_IndexDataStartOffset;
+ }
+
+ Uint32 NewMemoryBarriers = 0;
+ BindProgramResources( NewMemoryBarriers );
+
+ // NOTE: Base Vertex and Base Instance versions are not supported even in OpenGL ES 3.1
+ // This functionality can be emulated by adjusting stream offsets. This, however may cause
+ // errors in case instance data is read from the same stream as vertex data. Thus handling
+ // such cases is left to the application
+
+ // http://www.opengl.org/wiki/Vertex_Rendering
+ if( DrawAttribs.IsIndirect )
+ {
+ // The indirect rendering functions take their data from the buffer currently bound to the
+ // GL_DRAW_INDIRECT_BUFFER binding. Thus, any of indirect draw functions will fail if no buffer is
+ // bound to that binding.
+ VERIFY( DrawAttribs.pIndirectDrawAttribs, "Indirect draw command attributes buffer is not set" );
+ if( DrawAttribs.pIndirectDrawAttribs )
+ {
+ auto *pBufferOGL = static_cast<BufferGLImpl*>(DrawAttribs.pIndirectDrawAttribs);
+
+ pBufferOGL->BufferMemoryBarrier(
+ GL_COMMAND_BARRIER_BIT,// Command data sourced from buffer objects by
+ // Draw*Indirect and DispatchComputeIndirect commands after the barrier
+ // will reflect data written by shaders prior to the barrier.The buffer
+ // objects affected by this bit are derived from the DRAW_INDIRECT_BUFFER
+ // and DISPATCH_INDIRECT_BUFFER bindings.
+ m_ContextState);
+
+ glBindBuffer( GL_DRAW_INDIRECT_BUFFER, pBufferOGL->m_GlBuffer );
+ }
+
+ if( DrawAttribs.IsIndexed )
+ {
+ //typedef struct {
+ // GLuint count;
+ // GLuint instanceCount;
+ // GLuint firstIndex;
+ // GLuint baseVertex;
+ // GLuint baseInstance;
+ //} DrawElementsIndirectCommand;
+ glDrawElementsIndirect( GlTopology, IndexType, reinterpret_cast<const void*>( static_cast<size_t>(DrawAttribs.IndirectDrawArgsOffset) ) );
+ // Note that on GLES 3.1, baseInstance is present but reserved and must be zero
+ CHECK_GL_ERROR( "glDrawElementsIndirect() failed" );
+ }
+ else
+ {
+ //typedef struct {
+ // GLuint count;
+ // GLuint instanceCount;
+ // GLuint first;
+ // GLuint baseInstance;
+ //} DrawArraysIndirectCommand;
+ glDrawArraysIndirect( GlTopology, reinterpret_cast<const void*>( static_cast<size_t>(DrawAttribs.IndirectDrawArgsOffset) ) );
+ // Note that on GLES 3.1, baseInstance is present but reserved and must be zero
+ CHECK_GL_ERROR( "glDrawArraysIndirect() failed" );
+ }
+
+ glBindBuffer( GL_DRAW_INDIRECT_BUFFER, 0 );
+ }
+ else
+ {
+ if( DrawAttribs.NumInstances > 1 )
+ {
+ if( DrawAttribs.IsIndexed )
+ {
+ if( DrawAttribs.BaseVertex )
+ {
+ if( DrawAttribs.FirstInstanceLocation )
+ glDrawElementsInstancedBaseVertexBaseInstance( GlTopology, DrawAttribs.NumIndices, IndexType, reinterpret_cast<GLvoid*>( static_cast<size_t>(FirstIndexByteOffset) ), DrawAttribs.NumInstances, DrawAttribs.BaseVertex, DrawAttribs.FirstInstanceLocation );
+ else
+ glDrawElementsInstancedBaseVertex( GlTopology, DrawAttribs.NumIndices, IndexType, reinterpret_cast<GLvoid*>( static_cast<size_t>(FirstIndexByteOffset) ), DrawAttribs.NumInstances, DrawAttribs.BaseVertex );
+ }
+ else
+ {
+ if( DrawAttribs.FirstInstanceLocation )
+ glDrawElementsInstancedBaseInstance( GlTopology, DrawAttribs.NumIndices, IndexType, reinterpret_cast<GLvoid*>( static_cast<size_t>(FirstIndexByteOffset) ), DrawAttribs.NumInstances, DrawAttribs.FirstInstanceLocation );
+ else
+ glDrawElementsInstanced( GlTopology, DrawAttribs.NumIndices, IndexType, reinterpret_cast<GLvoid*>( static_cast<size_t>(FirstIndexByteOffset) ), DrawAttribs.NumInstances );
+ }
+ }
+ else
+ {
+ if( DrawAttribs.FirstInstanceLocation )
+ glDrawArraysInstancedBaseInstance( GlTopology, DrawAttribs.StartVertexLocation, DrawAttribs.NumVertices, DrawAttribs.NumInstances, DrawAttribs.FirstInstanceLocation );
+ else
+ glDrawArraysInstanced( GlTopology, DrawAttribs.StartVertexLocation, DrawAttribs.NumVertices, DrawAttribs.NumInstances );
+ }
+ }
+ else
+ {
+ if( DrawAttribs.IsIndexed )
+ {
+ if( DrawAttribs.BaseVertex )
+ glDrawElementsBaseVertex( GlTopology, DrawAttribs.NumIndices, IndexType, reinterpret_cast<GLvoid*>( static_cast<size_t>(FirstIndexByteOffset) ), DrawAttribs.BaseVertex );
+ else
+ glDrawElements( GlTopology, DrawAttribs.NumIndices, IndexType, reinterpret_cast<GLvoid*>( static_cast<size_t>(FirstIndexByteOffset) ) );
+ }
+ else
+ glDrawArrays( GlTopology, DrawAttribs.StartVertexLocation, DrawAttribs.NumVertices );
+ }
+ CHECK_GL_ERROR( "OpenGL draw command failed" );
+ }
+
+ // IMPORTANT: new pending memory barriers in the context must be set
+ // after all previous barriers were executed.
+ m_ContextState.SetPendingMemoryBarriers( NewMemoryBarriers );
+ }
+
+ void DeviceContextGLImpl::DispatchCompute( const DispatchComputeAttribs &DispatchAttrs )
+ {
+ Uint32 NewMemoryBarriers = 0;
+ BindProgramResources( NewMemoryBarriers );
+
+ if( DispatchAttrs.pIndirectDispatchAttribs )
+ {
+ CHECK_DYNAMIC_TYPE( BufferGLImpl, DispatchAttrs.pIndirectDispatchAttribs );
+ auto *pBufferOGL = static_cast<BufferGLImpl*>(DispatchAttrs.pIndirectDispatchAttribs);
+ pBufferOGL->BufferMemoryBarrier(
+ GL_COMMAND_BARRIER_BIT,// Command data sourced from buffer objects by
+ // Draw*Indirect and DispatchComputeIndirect commands after the barrier
+ // will reflect data written by shaders prior to the barrier.The buffer
+ // objects affected by this bit are derived from the DRAW_INDIRECT_BUFFER
+ // and DISPATCH_INDIRECT_BUFFER bindings.
+ m_ContextState);
+
+ glBindBuffer( GL_DISPATCH_INDIRECT_BUFFER, pBufferOGL->m_GlBuffer );
+ CHECK_GL_ERROR( "Failed to bind a buffer for dispatch indirect command" );
+
+ glDispatchComputeIndirect( DispatchAttrs.DispatchArgsByteOffset );
+ CHECK_GL_ERROR( "glDispatchComputeIndirect() failed" );
+
+ glBindBuffer( GL_DISPATCH_INDIRECT_BUFFER, 0 );
+ }
+ else
+ {
+ glDispatchCompute( DispatchAttrs.ThreadGroupCountX, DispatchAttrs.ThreadGroupCountY, DispatchAttrs.ThreadGroupCountZ );
+ CHECK_GL_ERROR( "glDispatchCompute() failed" );
+ }
+
+ // IMPORTANT: new pending memory barriers in the context must be set
+ // after all previous barriers were executed.
+ m_ContextState.SetPendingMemoryBarriers( NewMemoryBarriers );
+ }
+
+ void DeviceContextGLImpl::ClearDepthStencil( ITextureView *pView, Uint32 ClearFlags, float fDepth, Uint8 Stencil )
+ {
+ // Unlike OpenGL, in D3D10+, the full extent of the resource view is always cleared.
+ // Viewport and scissor settings are not applied.
+ if( pView != nullptr )
+ {
+ const auto& ViewDesc = pView->GetDesc();
+ VERIFY( ViewDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL, "Incorrect view type: depth stencil is expected" );
+ CHECK_DYNAMIC_TYPE( TextureViewGLImpl, pView );
+ auto *pViewGL = static_cast<TextureViewGLImpl*>(pView);
+ if( pView != m_pBoundDepthStencil )
+ {
+ UNEXPECTED( "Depth stencil buffer being cleared is not bound to the pipeline" );
+ LOG_ERROR_MESSAGE( "Depth stencil buffer must be bound to the pipeline to be cleared" );
+ }
+ }
+ else
+ {
+ if( !(nullptr == m_pBoundDepthStencil && m_pBoundRenderTargets.size() == 0) )
+ {
+ UNEXPECTED( "Default depth stencil buffer being cleared is not bound to the pipeline" );
+ LOG_ERROR_MESSAGE( "Default depth stencil buffer must be bound to the pipeline to be cleared" );
+ }
+ }
+ Uint32 glClearFlags = 0;
+ if( ClearFlags & CLEAR_DEPTH_FLAG ) glClearFlags |= GL_DEPTH_BUFFER_BIT;
+ if( ClearFlags & CLEAR_STENCIL_FLAG ) glClearFlags |= GL_STENCIL_BUFFER_BIT;
+ glClearDepthf( fDepth );
+ glClearStencil( Stencil );
+ // If depth writes are disabled, glClear() will not clear depth buffer!
+ bool DepthWritesEnabled = m_ContextState.GetDepthWritesEnabled();
+ m_ContextState.EnableDepthWrites( True );
+ bool ScissorTestEnabled = m_ContextState.GetScissorTestEnabled();
+ m_ContextState.EnableScissorTest( False );
+ // The pixel ownership test, the scissor test, dithering, and the buffer writemasks affect
+ // the operation of glClear. The scissor box bounds the cleared region. Alpha function,
+ // blend function, logical operation, stenciling, texture mapping, and depth-buffering
+ // are ignored by glClear.
+ glClear(glClearFlags);
+ CHECK_GL_ERROR( "glClear() failed" );
+ m_ContextState.EnableDepthWrites( DepthWritesEnabled );
+ m_ContextState.EnableScissorTest( ScissorTestEnabled );
+ }
+
+ void DeviceContextGLImpl::ClearRenderTarget( ITextureView *pView, const float *RGBA )
+ {
+ // Unlike OpenGL, in D3D10+, the full extent of the resource view is always cleared.
+ // Viewport and scissor settings are not applied.
+
+ Int32 RTIndex = -1;
+ if( pView != nullptr )
+ {
+ const auto& ViewDesc = pView->GetDesc();
+ VERIFY( ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET, "Incorrect view type: render target is expected" );
+ CHECK_DYNAMIC_TYPE( TextureViewGLImpl, pView );
+ auto *pViewGL = static_cast<TextureViewGLImpl*>(pView);
+ for( Uint32 rt = 0; rt < m_pBoundRenderTargets.size(); ++rt )
+ if( m_pBoundRenderTargets[rt] == pView )
+ {
+ RTIndex = rt;
+ break;
+ }
+
+ if( RTIndex == -1 )
+ {
+ UNEXPECTED( "Render target being cleared is not bound to the pipeline" );
+ LOG_ERROR_MESSAGE( "Render target must be bound to the pipeline to be cleared" );
+ }
+ }
+ else
+ {
+ if( m_pBoundRenderTargets.size() == 0 && m_pBoundDepthStencil == nullptr )
+ RTIndex = 0;
+ else
+ {
+ UNEXPECTED( "Default render target must be bound to the pipeline to be cleared" );
+ LOG_ERROR_MESSAGE( "Default render target must be bound to the pipeline to be cleared" );
+ }
+ }
+
+ static const float Zero[4] = { 0, 0, 0, 0 };
+ if( RGBA == nullptr )
+ RGBA = Zero;
+
+ // The pixel ownership test, the scissor test, dithering, and the buffer writemasks affect
+ // the operation of glClear. The scissor box bounds the cleared region. Alpha function,
+ // blend function, logical operation, stenciling, texture mapping, and depth-buffering
+ // are ignored by glClear.
+
+ // Disable scissor test
+ bool ScissorTestEnabled = m_ContextState.GetScissorTestEnabled();
+ m_ContextState.EnableScissorTest( False );
+
+ // Set write mask
+ Uint32 WriteMask = 0;
+ Bool bIndependentBlend = False;
+ m_ContextState.GetColorWriteMask( RTIndex, WriteMask, bIndependentBlend );
+ m_ContextState.SetColorWriteMask( RTIndex, COLOR_MASK_ALL, bIndependentBlend );
+
+ glClearBufferfv( GL_COLOR, RTIndex, RGBA );
+ CHECK_GL_ERROR( "glClearBufferfv() failed" );
+
+ m_ContextState.SetColorWriteMask( RTIndex, WriteMask, bIndependentBlend );
+ m_ContextState.EnableScissorTest( ScissorTestEnabled );
+ }
+
+ void DeviceContextGLImpl::Flush()
+ {
+ glFlush();
+ }
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/FBOCache.cpp b/Graphics/GraphicsEngineOpenGL/src/FBOCache.cpp
new file mode 100644
index 00000000..d3f50635
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/FBOCache.cpp
@@ -0,0 +1,280 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "FBOCache.h"
+#include "RenderDeviceGLImpl.h"
+#include "TextureBaseGL.h"
+#include "GLContextState.h"
+
+namespace Diligent
+{
+
+bool FBOCache::FBOCacheKey::operator == (const FBOCacheKey &Key)const
+{
+ if( Hash !=0 && Key.Hash !=0 && Hash != Key.Hash )
+ return false;
+
+ if( NumRenderTargets != Key.NumRenderTargets )
+ return false;
+ for( Uint32 rt = 0; rt < NumRenderTargets;++rt )
+ {
+ if( RTIds[rt] != Key.RTIds[rt] )
+ return false;
+ if( RTIds[rt] )
+ {
+ if( !(RTVDescs[rt] == Key.RTVDescs[rt]) )
+ return false;
+ }
+ }
+ if( DSId != Key.DSId )
+ return false;
+ if( DSId )
+ {
+ if( !(DSVDesc == Key.DSVDesc) )
+ return false;
+ }
+ return true;
+}
+
+std::size_t FBOCache::FBOCacheKeyHashFunc::operator() ( const FBOCacheKey& Key )const
+{
+ if( Key.Hash == 0 )
+ {
+ std::hash<TextureViewDesc> TexViewDescHasher;
+ Key.Hash = 0;
+ HashCombine( Key.Hash, Key.NumRenderTargets );
+ for( Uint32 rt = 0; rt < Key.NumRenderTargets; ++rt )
+ {
+ HashCombine( Key.Hash, Key.RTIds[rt] );
+ if( Key.RTIds[rt] )
+ HashCombine( Key.Hash, TexViewDescHasher( Key.RTVDescs[rt] ) );
+ }
+ HashCombine( Key.Hash, Key.DSId );
+ if( Key.DSId )
+ HashCombine( Key.Hash, TexViewDescHasher( Key.DSVDesc ) );
+ }
+ return Key.Hash;
+}
+
+
+FBOCache::FBOCache()
+{
+ m_Cache.max_load_factor(0.5f);
+ m_TexIdToKey.max_load_factor(0.5f);
+}
+
+FBOCache::~FBOCache()
+{
+ VERIFY( m_Cache.empty(), "FBO cache is not empty. Are there any unreleased objects?" );
+ VERIFY( m_TexIdToKey.empty(), "TexIdToKey cache is not empty.");
+}
+
+void FBOCache::OnReleaseTexture(ITexture *pTexture)
+{
+ ThreadingTools::LockHelper CacheLock(m_CacheLockFlag);
+ auto *pTexGL = ValidatedCast<TextureBaseGL>( pTexture );
+ // Find all FBOs that this texture used in
+ auto EqualRange = m_TexIdToKey.equal_range(pTexGL->GetUniqueID());
+ for(auto It = EqualRange.first; It != EqualRange.second; ++It)
+ {
+ m_Cache.erase(It->second);
+ }
+ m_TexIdToKey.erase(EqualRange.first, EqualRange.second);
+}
+
+const GLObjectWrappers::GLFrameBufferObj& FBOCache::GetFBO( Uint32 NumRenderTargets,
+ ITextureView *ppRenderTargets[],
+ ITextureView *pDepthStencil,
+ GLContextState &ContextState )
+{
+ // Pop null render targets from the end of the list
+ while( NumRenderTargets > 0 && ppRenderTargets[NumRenderTargets - 1] == nullptr )
+ --NumRenderTargets;
+
+ if( NumRenderTargets == 0 && pDepthStencil == nullptr )
+ {
+ static const GLObjectWrappers::GLFrameBufferObj DefaultFBO( false );
+ return DefaultFBO;
+ }
+
+ // Lock the cache
+ ThreadingTools::LockHelper CacheLock(m_CacheLockFlag);
+
+ // Construct the key
+ FBOCacheKey Key;
+ VERIFY( NumRenderTargets < MaxRenderTargets, "Too many render targets being set" );
+ NumRenderTargets = std::min( NumRenderTargets, MaxRenderTargets );
+ Key.NumRenderTargets = NumRenderTargets;
+ for( Uint32 rt = 0; rt < NumRenderTargets; ++rt )
+ {
+ auto *pRTView = ppRenderTargets[rt];
+ if( !pRTView )
+ continue;
+
+ auto *pTex = pRTView->GetTexture();
+ CHECK_DYNAMIC_TYPE( TextureBaseGL, pTex );
+ auto *pTexGL = static_cast<TextureBaseGL*>(pTex);
+ pTexGL->TextureMemoryBarrier(
+ GL_FRAMEBUFFER_BARRIER_BIT,// Reads and writes via framebuffer object attachments after the
+ // barrier will reflect data written by shaders prior to the barrier.
+ // Additionally, framebuffer writes issued after the barrier will wait
+ // on the completion of all shader writes issued prior to the barrier.
+ ContextState);
+
+ Key.RTIds[rt] = pTexGL->GetUniqueID();
+ Key.RTVDescs[rt] = pRTView->GetDesc();
+ }
+
+ if( pDepthStencil )
+ {
+ auto *pTex = pDepthStencil->GetTexture();
+ CHECK_DYNAMIC_TYPE( TextureBaseGL, pTex );
+ auto *pTexGL = static_cast<TextureBaseGL*>(pTex);
+ pTexGL->TextureMemoryBarrier( GL_FRAMEBUFFER_BARRIER_BIT, ContextState );
+ Key.DSId = pTexGL->GetUniqueID();
+ Key.DSVDesc = pDepthStencil->GetDesc();
+ }
+
+ // Try to find FBO in the map
+ auto It = m_Cache.find(Key);
+ if( It != m_Cache.end() )
+ {
+ return It->second;
+ }
+ else
+ {
+ // Create new FBO
+ GLObjectWrappers::GLFrameBufferObj NewFBO(true);
+
+ ContextState.BindFBO(NewFBO);
+
+ // Initialize FBO
+ for( Uint32 rt = 0; rt < NumRenderTargets; ++rt )
+ {
+ if( auto *pRTView = ppRenderTargets[rt] )
+ {
+ auto *pTexture = pRTView->GetTexture();
+ const auto &ViewDesc = pRTView->GetDesc();
+ CHECK_DYNAMIC_TYPE( TextureBaseGL, pTexture );
+ auto *pTexGL = static_cast<TextureBaseGL*>(pTexture);
+ pTexGL->AttachToFramebuffer( ViewDesc, GL_COLOR_ATTACHMENT0 + rt );
+ }
+ }
+
+ if( auto *pDSView = pDepthStencil )
+ {
+ auto *pTexture = pDSView->GetTexture();
+ const auto &ViewDesc = pDSView->GetDesc();
+ CHECK_DYNAMIC_TYPE( TextureBaseGL, pTexture );
+ auto *pTexGL = static_cast<TextureBaseGL*>(pTexture);
+ GLenum AttachmentPoint = 0;
+ if( ViewDesc.Format == TEX_FORMAT_D32_FLOAT ||
+ ViewDesc.Format == TEX_FORMAT_D16_UNORM )
+ {
+ auto GLTexFmt = pTexGL->GetGLTexFormat();
+ VERIFY( GLTexFmt == GL_DEPTH_COMPONENT32F || GLTexFmt == GL_DEPTH_COMPONENT16,
+ "Inappropriate internal texture format (", GLTexFmt, ") for depth attachment. "
+ "GL_DEPTH_COMPONENT32F or GL_DEPTH_COMPONENT16 is expected");
+
+ AttachmentPoint = GL_DEPTH_ATTACHMENT;
+ }
+ else if( ViewDesc.Format == TEX_FORMAT_D32_FLOAT_S8X24_UINT ||
+ ViewDesc.Format == TEX_FORMAT_D24_UNORM_S8_UINT )
+ {
+ auto GLTexFmt = pTexGL->GetGLTexFormat();
+ VERIFY( GLTexFmt == GL_DEPTH24_STENCIL8 || GLTexFmt == GL_DEPTH32F_STENCIL8,
+ "Inappropriate internal texture format (", GLTexFmt, ") for depth-stencil attachment. "
+ "GL_DEPTH24_STENCIL8 or GL_DEPTH32F_STENCIL8 is expected");
+
+ AttachmentPoint = GL_DEPTH_STENCIL_ATTACHMENT;
+ }
+ else
+ {
+ UNEXPECTED( GetTextureFormatAttribs(ViewDesc.Format).Name, " is not valid depth-stencil view format" );
+ }
+ pTexGL->AttachToFramebuffer( ViewDesc, AttachmentPoint );
+ }
+
+ // We now need to set mapping between shader outputs and
+ // color attachments. This largely redundant step is performed
+ // by glDrawBuffers()
+ static const GLenum DrawBuffers[] =
+ {
+ GL_COLOR_ATTACHMENT0,
+ GL_COLOR_ATTACHMENT1,
+ GL_COLOR_ATTACHMENT2,
+ GL_COLOR_ATTACHMENT3,
+ GL_COLOR_ATTACHMENT4,
+ GL_COLOR_ATTACHMENT5,
+ GL_COLOR_ATTACHMENT6,
+ GL_COLOR_ATTACHMENT7,
+ GL_COLOR_ATTACHMENT8,
+ GL_COLOR_ATTACHMENT9,
+ GL_COLOR_ATTACHMENT10,
+ GL_COLOR_ATTACHMENT11,
+ GL_COLOR_ATTACHMENT12,
+ GL_COLOR_ATTACHMENT13,
+ GL_COLOR_ATTACHMENT14,
+ GL_COLOR_ATTACHMENT15
+ };
+ // The state set by glDrawBuffers() is part of the state of the framebuffer.
+ // So it can be set up once and left it set.
+ glDrawBuffers(NumRenderTargets, DrawBuffers);
+ CHECK_GL_ERROR( "Failed to set draw buffers via glDrawBuffers()" );
+
+ GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if( Status != GL_FRAMEBUFFER_COMPLETE )
+ {
+ const Char *StatusString = "Unknown";
+ switch( Status )
+ {
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: StatusString = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: StatusString = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: StatusString = "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"; break;
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: StatusString = "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"; break;
+ case GL_FRAMEBUFFER_UNSUPPORTED: StatusString = "GL_FRAMEBUFFER_UNSUPPORTED"; break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: StatusString = "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; break;
+ case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: StatusString = "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"; break;
+ }
+ LOG_ERROR( "Framebuffer is incomplete. FB status: ", StatusString );
+ UNEXPECTED( "Framebuffer is incomplete" );
+ }
+
+ auto NewElems = m_Cache.emplace( make_pair(Key, std::move(NewFBO)) );
+ // New element must be actually inserted
+ VERIFY( NewElems.second, "New element was not inserted" );
+ if( Key.DSId )
+ m_TexIdToKey.insert( make_pair(Key.DSId, Key) );
+ for( Uint32 rt = 0; rt < NumRenderTargets; ++rt )
+ {
+ if( Key.RTIds[rt] )
+ m_TexIdToKey.insert( make_pair(Key.RTIds[rt], Key) );
+ }
+
+ return NewElems.first->second;
+ }
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/GLContextAndroid.cpp b/Graphics/GraphicsEngineOpenGL/src/GLContextAndroid.cpp
new file mode 100644
index 00000000..99ad25d0
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/GLContextAndroid.cpp
@@ -0,0 +1,399 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "GLContextAndroid.h"
+
+#ifndef EGL_CONTEXT_MINOR_VERSION_KHR
+#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
+#endif
+
+#ifndef EGL_CONTEXT_MAJOR_VERSION_KHR
+#define EGL_CONTEXT_MAJOR_VERSION_KHR EGL_CONTEXT_CLIENT_VERSION
+#endif
+
+namespace Diligent
+{
+ bool GLContext::InitEGLSurface()
+ {
+ display_ = eglGetDisplay( EGL_DEFAULT_DISPLAY );
+ if( display_ == EGL_NO_DISPLAY )
+ {
+ LOG_ERROR_AND_THROW( "No EGL display found" );
+ }
+
+ auto success = eglInitialize( display_, 0, 0 );
+ if( !success )
+ {
+ LOG_ERROR_AND_THROW( "Failed to initialise EGL" );
+ }
+
+ /*
+ * Here specify the attributes of the desired configuration.
+ * Below, we select an EGLConfig with at least 8 bits per color
+ * component compatible with on-screen windows
+ */
+ const EGLint attribs[] =
+ {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //Request opengl ES2.0
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ //EGL_COLORSPACE, EGL_COLORSPACE_sRGB, // does not work
+ EGL_BLUE_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_RED_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 24,
+ //EGL_SAMPLE_BUFFERS , 1,
+ //EGL_SAMPLES , 4,
+ EGL_NONE
+ };
+ color_size_ = 8;
+ depth_size_ = 24;
+
+ // Get a list of EGL frame buffer configurations that match specified attributes
+ EGLint num_configs;
+ success = eglChooseConfig( display_, attribs, &config_, 1, &num_configs );
+ if( !success )
+ {
+ LOG_ERROR_AND_THROW( "Failed to choose config" );
+ }
+
+ if( !num_configs )
+ {
+ //Fall back to 16bit depth buffer
+ const EGLint attribs[] =
+ {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //Request opengl ES2.0
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_BLUE_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_RED_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 16,
+ EGL_NONE
+ };
+ success = eglChooseConfig( display_, attribs, &config_, 1, &num_configs );
+ if( !success )
+ {
+ LOG_ERROR_AND_THROW( "Failed to choose 16-bit depth config" );
+ }
+
+ depth_size_ = 16;
+ }
+
+ if( !num_configs )
+ {
+ LOG_ERROR_AND_THROW( "Unable to retrieve EGL config" );
+ }
+
+ surface_ = eglCreateWindowSurface( display_, config_, window_, NULL );
+ if( surface_ == EGL_NO_SURFACE )
+ {
+ LOG_ERROR_AND_THROW( "Failed to create EGLSurface" );
+ }
+
+ int32_t screen_width = 0, screen_height = 0;
+ eglQuerySurface( display_, surface_, EGL_WIDTH, &screen_width );
+ eglQuerySurface( display_, surface_, EGL_HEIGHT, &screen_height );
+ SwapChainAttribs_.Width = screen_width;
+ SwapChainAttribs_.Height = screen_height;
+
+ /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
+ * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
+ * As soon as we picked a EGLConfig, we can safely reconfigure the
+ * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
+ EGLint format;
+ eglGetConfigAttrib( display_, config_, EGL_NATIVE_VISUAL_ID, &format );
+ ANativeWindow_setBuffersGeometry( window_, 0, 0, format );
+
+ LoadGLFunctions();
+
+ return true;
+ }
+
+ bool GLContext::InitEGLContext()
+ {
+ major_version_ = 3;
+ minor_version_ = 1;
+
+ const EGLint context_attribs[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, major_version_,
+ EGL_CONTEXT_MINOR_VERSION_KHR, minor_version_,
+ EGL_NONE
+ };
+
+ LOG_INFO_MESSAGE( "contextAttribs: ", context_attribs[0], ' ', context_attribs[1], '\n' );
+ LOG_INFO_MESSAGE( "contextAttribs: ", context_attribs[2], ' ', context_attribs[3], '\n' );
+
+ context_ = eglCreateContext( display_, config_, NULL, context_attribs );
+ if( context_ == EGL_NO_CONTEXT )
+ {
+ LOG_ERROR_AND_THROW( "Failed to create EGLContext" );
+ }
+
+ if( eglMakeCurrent( display_, surface_, surface_, context_ ) == EGL_FALSE )
+ {
+ LOG_ERROR_AND_THROW( "Unable to eglMakeCurrent" );
+ }
+
+ context_valid_ = true;
+ return true;
+ }
+
+ void GLContext::InitGLES()
+ {
+ if( gles_initialized_ )
+ return;
+ //
+ //Initialize OpenGL ES 3 if available
+ //
+ LOG_INFO_MESSAGE( "GL Version: \n", glGetString( GL_VERSION ), '\n' );
+ const char* versionStr = (const char*)glGetString( GL_VERSION );
+ if( strstr( versionStr, "OpenGL ES 3." )
+#if USE_GL3_STUB
+ && gl3stubInit()
+#endif
+ )
+ {
+ es3_supported_ = true;
+ gl_version_ = 3.0f;
+ }
+ else
+ {
+ gl_version_ = 2.0f;
+ }
+
+ gles_initialized_ = true;
+ }
+
+ bool GLContext::Init( ANativeWindow* window )
+ {
+ if( egl_context_initialized_ )
+ return true;
+
+ //
+ //Initialize EGL
+ //
+ window_ = window;
+ InitEGLSurface();
+ InitEGLContext();
+ InitGLES();
+
+ egl_context_initialized_ = true;
+
+ return true;
+ }
+
+ GLContext::GLContext( const ContextInitInfo &Info, DeviceCaps &DeviceCaps ) :
+ display_( EGL_NO_DISPLAY ),
+ surface_( EGL_NO_SURFACE ),
+ context_( EGL_NO_CONTEXT ),
+ es3_supported_( false ),
+ egl_context_initialized_( false ),
+ gles_initialized_( false ),
+ major_version_(0),
+ minor_version_(0),
+ SwapChainAttribs_(Info.SwapChainAttribs)
+ {
+ auto *NativeWindow = reinterpret_cast<ANativeWindow*>(Info.pNativeWndHandle);
+ Init( NativeWindow );
+
+ FillDeviceCaps(DeviceCaps);
+#if 0
+ // Creates table of supported extensions strings
+ extensions.clear();
+ string tmp;
+ sint32 begin, end;
+ tmp = string( (char*)glGetString( GL_EXTENSIONS ) );
+
+ begin = 0;
+ end = tmp.find( ' ', 0 );
+
+ DEBUG_PRINT( _L( "Checking Extensions" ) );
+
+ while( end != string::npos )
+ {
+ DEBUG_PRINT( (_L( "extension %s" )), tmp.substr( begin, end - begin ).c_str() );
+ extensions.insert( extensions.end(), tmp.substr( begin, end - begin ) );
+ begin = end + 1;
+ end = tmp.find( ' ', begin );
+ }
+
+ if( supportExtension( "GL_INTEL_tessellation" ) )
+ {
+ glPatchParameteri = (PFNGLPATCHPARAMETERIPROC)eglGetProcAddress( "glPatchParameteri" );
+ DEBUG_PRINT( _L( "%s = %p" ), "glPatchParameteri", (void*)glPatchParameteri );
+ glPatchParameterfv = (PFNGLPATCHPARAMETERFVPROC)eglGetProcAddress( "glPatchParameterfv" );
+ DEBUG_PRINT( _L( "%s = %p" ), "glPatchParameterfv", (void*)glPatchParameterfv );
+ }
+ //if(supportExtension("GL_INTEL_compute_shader"))
+ {
+ glDispatchCompute = (PFNGLDISPATCHCOMPUTEPROC)eglGetProcAddress( "glDispatchCompute" );
+ DEBUG_PRINT( _L( "%s = %p" ), "glDispatchCompute", (void*)glDispatchCompute );
+ glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC)eglGetProcAddress( "glBindImageTexture" );
+ DEBUG_PRINT( _L( "%s = %p" ), "glBindImageTexture", (void*)glBindImageTexture );
+ }
+#endif
+ }
+
+ GLContext::~GLContext()
+ {
+ Terminate();
+ }
+
+ void GLContext::SwapBuffers()
+ {
+ bool b = eglSwapBuffers( display_, surface_ );
+ if( !b )
+ {
+ EGLint err = eglGetError();
+ if( err == EGL_BAD_SURFACE )
+ {
+ //Recreate surface
+ InitEGLSurface();
+ //return EGL_SUCCESS; //Still consider glContext is valid
+ }
+ else if( err == EGL_CONTEXT_LOST || err == EGL_BAD_CONTEXT )
+ {
+ //Context has been lost!!
+ context_valid_ = false;
+ Terminate();
+ InitEGLContext();
+ }
+ //return err;
+ }
+ //return EGL_SUCCESS;
+ }
+
+ void GLContext::Terminate()
+ {
+ if( display_ != EGL_NO_DISPLAY )
+ {
+ eglMakeCurrent( display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
+ if( context_ != EGL_NO_CONTEXT )
+ {
+ eglDestroyContext( display_, context_ );
+ }
+
+ if( surface_ != EGL_NO_SURFACE )
+ {
+ eglDestroySurface( display_, surface_ );
+ }
+ eglTerminate( display_ );
+ }
+
+ display_ = EGL_NO_DISPLAY;
+ context_ = EGL_NO_CONTEXT;
+ surface_ = EGL_NO_SURFACE;
+ context_valid_ = false;
+ }
+
+
+ EGLint GLContext::Resume( ANativeWindow* window )
+ {
+ if( egl_context_initialized_ == false )
+ {
+ Init( window );
+ return EGL_SUCCESS;
+ }
+
+
+ //Create surface
+ window_ = window;
+ surface_ = eglCreateWindowSurface( display_, config_, window_, NULL );
+ int32_t new_screen_width = 0;
+ int32_t new_screen_height = 0;
+ eglQuerySurface( display_, surface_, EGL_WIDTH, &new_screen_width );
+ eglQuerySurface( display_, surface_, EGL_HEIGHT, &new_screen_height );
+
+ if( new_screen_width != SwapChainAttribs_.Width || new_screen_height != SwapChainAttribs_.Height )
+ {
+ //Screen resized
+ LOG_INFO_MESSAGE( "Screen resized\n" );
+ }
+
+ if( eglMakeCurrent( display_, surface_, surface_, context_ ) == EGL_TRUE )
+ return EGL_SUCCESS;
+
+ EGLint err = eglGetError();
+ LOG_WARNING_MESSAGE( "Unable to eglMakeCurrent ", err, '\n' );
+
+ if( err == EGL_CONTEXT_LOST )
+ {
+ //Recreate context
+ LOG_INFO_MESSAGE( "Re-creating egl context\n" );
+ InitEGLContext();
+ }
+ else
+ {
+ //Recreate surface
+ Terminate();
+ InitEGLSurface();
+ InitEGLContext();
+ }
+
+ return err;
+
+ }
+
+ void GLContext::Suspend()
+ {
+ if( surface_ != EGL_NO_SURFACE )
+ {
+ eglDestroySurface( display_, surface_ );
+ surface_ = EGL_NO_SURFACE;
+ }
+ }
+
+ bool GLContext::Invalidate()
+ {
+ Terminate();
+
+ egl_context_initialized_ = false;
+ return true;
+ }
+
+ void GLContext::FillDeviceCaps( DeviceCaps &DeviceCaps )
+ {
+ DeviceCaps.DevType = DeviceType::OpenGLES;
+ DeviceCaps.MajorVersion = major_version_;
+ DeviceCaps.MinorVersion = minor_version_;
+ bool IsGLES31OrAbove = (major_version_ >= 4 || major_version_ == 3 && minor_version_ >= 1);
+ DeviceCaps.bSeparableProgramSupported = IsGLES31OrAbove;
+ DeviceCaps.bIndirectRenderingSupported = IsGLES31OrAbove;
+
+ auto &SamCaps = DeviceCaps.SamCaps;
+ SamCaps.bBorderSamplingModeSupported = GL_TEXTURE_BORDER_COLOR && IsGLES31OrAbove;
+ SamCaps.bAnisotropicFilteringSupported = GL_TEXTURE_MAX_ANISOTROPY_EXT && IsGLES31OrAbove;
+ SamCaps.bLODBiasSupported = GL_TEXTURE_LOD_BIAS && IsGLES31OrAbove;
+
+ auto &TexCaps = DeviceCaps.TexCaps;
+ TexCaps.bTexture1DSupported = False; // Not supported in GLES 3.1
+ TexCaps.bTexture1DArraySupported = False; // Not supported in GLES 3.1
+ TexCaps.bTexture2DMSSupported = IsGLES31OrAbove;
+ TexCaps.bTexture2DMSArraySupported = False; // Not supported in GLES 3.1
+ TexCaps.bTextureViewSupported = False; // Not supported in GLES 3.1
+ }
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/GLContextState.cpp b/Graphics/GraphicsEngineOpenGL/src/GLContextState.cpp
new file mode 100644
index 00000000..065f3a16
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/GLContextState.cpp
@@ -0,0 +1,647 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "GLContextState.h"
+#include "TextureBaseGL.h"
+#include "SamplerGLImpl.h"
+#include "AsyncWritableResource.h"
+#include "GLTypeConversions.h"
+#include "BufferViewGLImpl.h"
+#include "RenderDeviceGLImpl.h"
+
+using namespace GLObjectWrappers;
+using namespace Diligent;
+
+namespace Diligent
+{
+ GLContextState::GLContextState( RenderDeviceGLImpl *pDeviceGL ) :
+ m_PendingMemoryBarriers( 0 ),
+ m_DepthCmpFunc( COMPARISON_FUNC_UNKNOW ),
+ m_StencilReadMask( 0xFF ),
+ m_StencilWriteMask( 0xFF ),
+ m_GLProgId( 0 ),
+ m_GLPipelineId( 0 ),
+ m_VAOId( 0 ),
+ m_FBOId( 0 ),
+ m_iActiveTexture(-1)
+ {
+ const DeviceCaps &DeviceCaps = pDeviceGL->GetDeviceCaps();
+ m_Caps.bFillModeSelectionSupported = DeviceCaps.bWireframeFillSupported;
+
+ {
+ m_Caps.m_iMaxCombinedTexUnits = 0;
+ glGetIntegerv( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &m_Caps.m_iMaxCombinedTexUnits );
+ CHECK_GL_ERROR( "Failed to get max combined tex image units count" );
+ m_Caps.m_iMaxCombinedTexUnits = std::max( m_Caps.m_iMaxCombinedTexUnits, 80 ); // Must be at least 80 in GL4.2
+ }
+
+ m_BoundTextures.reserve( m_Caps.m_iMaxCombinedTexUnits );
+ m_BoundSamplers.reserve( 32 );
+ m_pBoundImages.reserve( 32 );
+
+ for( Uint32 rt = 0; rt < _countof( m_ColorWriteMasks ); ++rt )
+ m_ColorWriteMasks[rt] = COLOR_MASK_ALL;
+ }
+
+ template<typename ObjectType>
+ bool UpdateBoundObject( UniqueIdentifier &CurrentObjectID, const ObjectType &NewObject, GLuint &NewGLHandle )
+ {
+ NewGLHandle = static_cast<GLuint>(NewObject);
+ UniqueIdentifier NewObjectID = 0;
+ if( NewGLHandle != 0 )
+ {
+ // Only ask for the ID if the object handle is non-zero
+ // to avoid ID generation for null objects
+ NewObjectID = NewObject.GetUniqueID();
+ }
+
+ // It is unsafe to use GL handle to keep track of bound textures
+ // When a texture is released, GL is free to reuse its handle for
+ // the new created textures
+ if( CurrentObjectID != NewObjectID )
+ {
+ CurrentObjectID = NewObjectID;
+ return true;
+ }
+ return false;
+ }
+
+ void GLContextState::SetProgram( const GLProgramObj &GLProgram )
+ {
+ GLuint GLProgHandle = 0;
+ if( UpdateBoundObject( m_GLProgId, GLProgram, GLProgHandle ) )
+ {
+ glUseProgram( GLProgHandle );
+ CHECK_GL_ERROR( "Failed to set GL program" );
+ }
+ }
+
+ void GLContextState::SetPipeline( const GLPipelineObj &GLPipeline )
+ {
+ GLuint GLPipelineHandle = 0;
+ if( UpdateBoundObject( m_GLPipelineId, GLPipeline, GLPipelineHandle ) )
+ {
+ glBindProgramPipeline( GLPipelineHandle );
+ CHECK_GL_ERROR( "Failed to bind program pipeline" );
+ }
+ }
+
+ void GLContextState::BindVAO( const GLVertexArrayObj &VAO )
+ {
+ GLuint VAOHandle = 0;
+ if( UpdateBoundObject( m_VAOId, VAO, VAOHandle ) )
+ {
+ VERIFY( VAOHandle, "VAO Handle is zero" );
+ glBindVertexArray( VAOHandle );
+ CHECK_GL_ERROR( "Failed to set VAO" );
+ }
+ }
+
+ void GLContextState::BindFBO( const GLFrameBufferObj &FBO )
+ {
+ GLuint FBOHandle = 0;
+ if( UpdateBoundObject( m_FBOId, FBO, FBOHandle ) )
+ {
+ // Even though the write mask only applies to writes to a framebuffer, the mask state is NOT
+ // Framebuffer state. So it is NOT part of a Framebuffer Object or the Default Framebuffer.
+ // Binding a new framebuffer will NOT affect the mask.
+
+ // NOTE: if attachment image is a NON-immutable format texture and the selected
+ // level is NOT level_base, the texture MUST BE MIPMAP COMPLETE
+ // If image is part of a cubemap texture, the texture must also be mipmap cube complete.
+ glBindFramebuffer( GL_DRAW_FRAMEBUFFER, FBOHandle );
+ CHECK_GL_ERROR( "Failed to bind FBO as draw framebuffer" );
+ glBindFramebuffer( GL_READ_FRAMEBUFFER, FBOHandle );
+ CHECK_GL_ERROR( "Failed to bind FBO as read framebuffer" );
+ }
+ }
+
+ template<class ObjectType>
+ bool UpdateBoundObjectsArr( std::vector< UniqueIdentifier >& BoundObjectIDs, Uint32 Index, const ObjectType &NewObject, GLuint &NewGLHandle )
+ {
+ if( Index >= BoundObjectIDs.size() )
+ BoundObjectIDs.resize( Index + 1 );
+
+ return UpdateBoundObject( BoundObjectIDs[Index], NewObject, NewGLHandle );
+ }
+
+ void GLContextState::SetActiveTexture( Int32 Index )
+ {
+ if( Index < 0 )
+ {
+ Index += m_Caps.m_iMaxCombinedTexUnits;
+ }
+ VERIFY( 0 <= Index && Index < m_Caps.m_iMaxCombinedTexUnits, "Texture unit is out of range" );
+
+ if( m_iActiveTexture != Index )
+ {
+ glActiveTexture( GL_TEXTURE0 + Index );
+ CHECK_GL_ERROR( "Failed to activate texture slot ", Index );
+ m_iActiveTexture = Index;
+ }
+ }
+
+ void GLContextState::BindTexture( Int32 Index, GLenum BindTarget, const GLObjectWrappers::GLTextureObj &Tex)
+ {
+ if( Index < 0 )
+ {
+ Index += m_Caps.m_iMaxCombinedTexUnits;
+ }
+ VERIFY( 0 <= Index && Index < m_Caps.m_iMaxCombinedTexUnits, "Texture unit is out of range" );
+
+ // Always update active texture unit
+ SetActiveTexture( Index );
+
+ GLuint GLTexHandle = 0;
+ if( UpdateBoundObjectsArr( m_BoundTextures, Index, Tex, GLTexHandle ) )
+ {
+ glBindTexture( BindTarget, GLTexHandle );
+ CHECK_GL_ERROR( "Failed to bind texture to slot ", Index );
+ }
+ }
+
+ void GLContextState::BindSampler( Uint32 Index, const GLObjectWrappers::GLSamplerObj &GLSampler)
+ {
+ GLuint GLSamplerHandle = 0;
+ if( UpdateBoundObjectsArr( m_BoundSamplers, Index, GLSampler, GLSamplerHandle ) )
+ {
+ glBindSampler( Index, GLSamplerHandle );
+ CHECK_GL_ERROR( "Failed to bind sampler to slot ", Index );
+ }
+ }
+
+ void GLContextState::BindImage( Uint32 Index,
+ TextureViewGLImpl *pTexView,
+ GLint MipLevel,
+ GLboolean IsLayered,
+ GLint Layer,
+ GLenum Access,
+ GLenum Format )
+ {
+ BoundImageInfo NewImageInfo(
+ pTexView->GetUniqueID(),
+ MipLevel,
+ IsLayered,
+ Layer,
+ Access,
+ Format
+ );
+ if( Index >= m_pBoundImages.size() )
+ m_pBoundImages.resize( Index + 1 );
+ if( !(m_pBoundImages[Index] == NewImageInfo) )
+ {
+ m_pBoundImages[Index] = NewImageInfo;
+ GLint GLTexHandle = pTexView->GetHandle();
+ glBindImageTexture( Index, GLTexHandle, MipLevel, IsLayered, Layer, Access, Format );
+ CHECK_GL_ERROR( "glBindImageTexture() failed" );
+ }
+ }
+
+ void GLContextState::EnsureMemoryBarrier( Uint32 RequiredBarriers, AsyncWritableResource *pRes/* = nullptr */ )
+ {
+ // Every resource tracks its own pending memory barriers.
+ // Device context also tracks which barriers have not been executed
+ // When a resource with pending memory barrier flag is bound to the context,
+ // the context checks if the same flag is set in its own pending barriers.
+ // Thus a memory barrier is only executed if some resource required that barrier
+ // and it has not been executed yet. This is almost optimal strategy, but slightly
+ // imperfect as the following scenario shows:
+
+ // Draw 1: Barriers_A |= BARRIER_FLAG, Barrier_Ctx |= BARRIER_FLAG
+ // Draw 2: Barriers_B |= BARRIER_FLAG, Barrier_Ctx |= BARRIER_FLAG
+ // Draw 3: Bind B, execute BARRIER: Barriers_B = 0, Barrier_Ctx = 0 (Barriers_A == BARRIER_FLAG)
+ // Draw 4: Barriers_B |= BARRIER_FLAG, Barrier_Ctx |= BARRIER_FLAG
+ // Draw 5: Bind A, execute BARRIER, Barriers_A = 0, Barrier_Ctx = 0 (Barriers_B == BARRIER_FLAG)
+
+ // In the last draw call, barrier for resource A has already been executed when resource B was
+ // bound to the pipeline. Since Resource A has not been bound since then, its flag has not been
+ // cleared.
+ // This situation does not seem to be a problem though since a barier cannot be executed
+ // twice in any situation
+
+ Uint32 ResourcePendingBarriers = 0;
+ if( pRes )
+ {
+ // If resource is specified, only set up memory barriers
+ // that are required by the resource
+ ResourcePendingBarriers = pRes->GetPendingMemortBarriers();
+ RequiredBarriers &= ResourcePendingBarriers;
+ }
+
+ // Leave only pending barriers
+ RequiredBarriers &= m_PendingMemoryBarriers;
+ if( RequiredBarriers )
+ {
+ glMemoryBarrier( RequiredBarriers );
+ CHECK_GL_ERROR( "glMemoryBarrier() failed" );
+ m_PendingMemoryBarriers &= ~RequiredBarriers;
+ }
+
+ // Leave only these barriers that are still pending
+ if( pRes )
+ pRes->ResetPendingMemoryBarriers( m_PendingMemoryBarriers & ResourcePendingBarriers );
+ }
+
+ void GLContextState::SetPendingMemoryBarriers( Uint32 PendingBarriers )
+ {
+ m_PendingMemoryBarriers |= PendingBarriers;
+ }
+
+ void GLContextState::EnableDepthTest( bool bEnable )
+ {
+ if( m_DepthEnableState != bEnable )
+ {
+ if( bEnable )
+ {
+ glEnable( GL_DEPTH_TEST );
+ CHECK_GL_ERROR( "Failed to enable detph test" );
+ }
+ else
+ {
+ glDisable( GL_DEPTH_TEST );
+ CHECK_GL_ERROR( "Failed to disable detph test" );
+ }
+ m_DepthEnableState = bEnable;
+ }
+ }
+
+ void GLContextState::EnableDepthWrites( bool bEnable )
+ {
+ if( m_DepthWritesEnableState != bEnable )
+ {
+ // If mask is non-zero, the depth buffer is enabled for writing; otherwise, it is disabled.
+ glDepthMask( bEnable ? 1 : 0 );
+ CHECK_GL_ERROR( "Failed to enale/disable depth writes" );
+ m_DepthWritesEnableState = bEnable;
+ }
+ }
+
+ void GLContextState::SetDepthFunc( COMPARISON_FUNCTION CmpFunc )
+ {
+ if( m_DepthCmpFunc != CmpFunc )
+ {
+ auto GlCmpFunc = CompareFuncToGLCompareFunc( CmpFunc );
+ glDepthFunc( GlCmpFunc );
+ CHECK_GL_ERROR( "Failed to set GL comparison function" );
+ m_DepthCmpFunc = CmpFunc;
+ }
+ }
+
+ void GLContextState::EnableStencilTest( bool bEnable )
+ {
+ if( m_StencilTestEnableState != bEnable )
+ {
+ if( bEnable )
+ {
+ glEnable( GL_STENCIL_TEST );
+ CHECK_GL_ERROR( "Failed to enable stencil test" );
+ }
+ else
+ {
+ glDisable( GL_STENCIL_TEST );
+ CHECK_GL_ERROR( "Failed to disable stencil test" );
+ }
+ m_StencilTestEnableState = bEnable;
+ }
+ }
+
+ void GLContextState::SetStencilWriteMask( Uint8 StencilWriteMask )
+ {
+ if( m_StencilWriteMask != StencilWriteMask )
+ {
+ glStencilMask( StencilWriteMask );
+ m_StencilWriteMask = StencilWriteMask;
+ }
+ }
+
+ void GLContextState::SetStencilFunc( GLenum Face, COMPARISON_FUNCTION Func, Int32 Ref, Uint32 Mask )
+ {
+ auto& FaceStencilOp = m_StencilOpState[Face == GL_FRONT ? 0 : 1];
+ if( FaceStencilOp.Func != Func ||
+ FaceStencilOp.Ref != Ref ||
+ FaceStencilOp.Mask != Mask )
+ {
+ auto GlStencilFunc = CompareFuncToGLCompareFunc( Func );
+ glStencilFuncSeparate( Face, GlStencilFunc, Ref, Mask );
+ CHECK_GL_ERROR( "Failed to set stencil function" );
+
+ FaceStencilOp.Func = Func;
+ FaceStencilOp.Ref = Ref;
+ FaceStencilOp.Mask = Mask;
+ }
+ }
+
+ void GLContextState::SetStencilOp( GLenum Face, STENCIL_OP StencilFailOp, STENCIL_OP StencilDepthFailOp, STENCIL_OP StencilPassOp )
+ {
+ auto& FaceStencilOp = m_StencilOpState[Face == GL_FRONT ? 0 : 1];
+ if( FaceStencilOp.StencilFailOp != StencilFailOp ||
+ FaceStencilOp.StencilDepthFailOp != StencilDepthFailOp ||
+ FaceStencilOp.StencilPassOp != StencilPassOp )
+ {
+ auto glsfail = StencilOp2GlStencilOp( StencilFailOp );
+ auto dpfail = StencilOp2GlStencilOp( StencilDepthFailOp );
+ auto dppass = StencilOp2GlStencilOp( StencilPassOp );
+
+ glStencilOpSeparate( Face, glsfail, dpfail, dppass );
+ CHECK_GL_ERROR( "Failed to set stencil operation" );
+
+ FaceStencilOp.StencilFailOp = StencilFailOp;
+ FaceStencilOp.StencilDepthFailOp = StencilDepthFailOp;
+ FaceStencilOp.StencilPassOp = StencilPassOp;
+ }
+ }
+
+ void GLContextState::SetFillMode( FILL_MODE FillMode )
+ {
+ if( m_Caps.bFillModeSelectionSupported )
+ {
+ if( m_RSState.FillMode != FillMode )
+ {
+ auto PolygonMode = FillMode == FILL_MODE_WIREFRAME ? GL_LINE : GL_FILL;
+ glPolygonMode( GL_FRONT_AND_BACK, PolygonMode );
+ CHECK_GL_ERROR( "Failed to set polygon mode" );
+
+ m_RSState.FillMode = FillMode;
+ }
+ }
+ else
+ {
+ if( FillMode == FILL_MODE_WIREFRAME )
+ LOG_WARNING_MESSAGE( "Wireframe fill mode is not supported on this device\n" );
+ }
+ }
+
+ void GLContextState::SetCullMode( CULL_MODE CullMode )
+ {
+ if( m_RSState.CullMode != CullMode )
+ {
+ if( CullMode == CULL_MODE_NONE )
+ {
+ glDisable( GL_CULL_FACE );
+ CHECK_GL_ERROR( "Failed to disable face culling" );
+ }
+ else
+ {
+ VERIFY( CullMode == CULL_MODE_FRONT || CullMode == CULL_MODE_BACK, "Unexpected cull mode" );
+ glEnable( GL_CULL_FACE );
+ CHECK_GL_ERROR( "Failed to enable face culling" );
+ auto CullFace = CullMode == CULL_MODE_BACK ? GL_BACK : GL_FRONT;
+ glCullFace( CullFace );
+ CHECK_GL_ERROR( "Failed to set cull face" );
+ }
+
+ m_RSState.CullMode = CullMode;
+ }
+ }
+
+ void GLContextState::SetFrontFace( Bool FrontCounterClockwise )
+ {
+ if( m_RSState.FrontCounterClockwise != FrontCounterClockwise )
+ {
+ auto FrontFace = FrontCounterClockwise ? GL_CCW : GL_CW;
+ glFrontFace( FrontFace );
+ CHECK_GL_ERROR( "Failed to set front face" );
+ m_RSState.FrontCounterClockwise = FrontCounterClockwise;
+ }
+ }
+
+ void GLContextState::SetDepthBias( float fDepthBias, float fSlopeScaledDepthBias )
+ {
+ if( m_RSState.fDepthBias != fDepthBias ||
+ m_RSState.fSlopeScaledDepthBias != fSlopeScaledDepthBias )
+ {
+ if( fDepthBias != 0 || fSlopeScaledDepthBias != 0 )
+ {
+ glEnable( GL_POLYGON_OFFSET_FILL );
+ CHECK_GL_ERROR( "Failed to enable polygon offset fill" );
+ }
+ else
+ {
+ glDisable( GL_POLYGON_OFFSET_FILL );
+ CHECK_GL_ERROR( "Failed to disable polygon offset fill" );
+ }
+
+ glPolygonOffset( fSlopeScaledDepthBias, fDepthBias );
+ CHECK_GL_ERROR( "Failed to set polygon offset" );
+
+ m_RSState.fDepthBias = fDepthBias;
+ m_RSState.fSlopeScaledDepthBias = fSlopeScaledDepthBias;
+ }
+ }
+
+ void GLContextState::SetDepthClamp( Bool bEnableDepthClamp )
+ {
+ if( m_RSState.DepthClampEnable != bEnableDepthClamp )
+ {
+ if( bEnableDepthClamp )
+ {
+ if( GL_DEPTH_CLAMP )
+ {
+ glEnable( GL_DEPTH_CLAMP );
+ CHECK_GL_ERROR( "Failed to enable depth clamp" );
+ }
+ }
+ else
+ {
+ if( GL_DEPTH_CLAMP )
+ {
+ // WARNING: on OpenGL, depth clamping is disabled against
+ // both far and near clip planes. On DirectX, only clipping
+ // against far clip plane can be disabled
+ glDisable( GL_DEPTH_CLAMP );
+ CHECK_GL_ERROR( "Failed to disable depth clamp" );
+ }
+ else
+ {
+ LOG_WARNING_MESSAGE( "Disabling depth clamp is not supported" )
+ }
+ }
+ m_RSState.DepthClampEnable = bEnableDepthClamp;
+ }
+ }
+
+ void GLContextState::EnableScissorTest( Bool bEnableScissorTest )
+ {
+ if( m_RSState.ScissorTestEnable != bEnableScissorTest )
+ {
+ if( bEnableScissorTest )
+ {
+ glEnable( GL_SCISSOR_TEST );
+ CHECK_GL_ERROR( "Failed to enable scissor test" );
+ }
+ else
+ {
+ glDisable( GL_SCISSOR_TEST );
+ CHECK_GL_ERROR( "Failed to disable scissor clamp" );
+ }
+
+ m_RSState.ScissorTestEnable = bEnableScissorTest;
+ }
+ }
+
+ void GLContextState::SetBlendState( const BlendStateDesc &BSDsc, const float *BlendFactors, Uint32 SampleMask )
+ {
+ bool bEnableBlend = false;
+ if( BSDsc.IndependentBlendEnable )
+ {
+ for( int i = 0; i < BSDsc.MaxRenderTargets; ++i )
+ {
+ const auto& RT = BSDsc.RenderTargets[i];
+ if( RT.BlendEnable )
+ bEnableBlend = true;
+
+ SetColorWriteMask(i, RT.RenderTargetWriteMask, True);
+ }
+ }
+ else
+ {
+ const auto& RT0 = BSDsc.RenderTargets[0];
+ bEnableBlend = RT0.BlendEnable;
+ SetColorWriteMask(0, RT0.RenderTargetWriteMask, False);
+ }
+
+ if( bEnableBlend )
+ {
+ // Sets the blend enable flag for ALL color buffers.
+ glEnable( GL_BLEND );
+ CHECK_GL_ERROR( "Failed to enable alpha blending" );
+
+ glBlendColor( BlendFactors[0], BlendFactors[1], BlendFactors[2], BlendFactors[3] );
+ CHECK_GL_ERROR( "Failed to set blend color" );
+
+ if( BSDsc.AlphaToCoverageEnable )
+ {
+ glEnable( GL_SAMPLE_ALPHA_TO_COVERAGE );
+ CHECK_GL_ERROR( "Failed to enable alpha to coverage" );
+ }
+ else
+ {
+ glDisable( GL_SAMPLE_ALPHA_TO_COVERAGE );
+ CHECK_GL_ERROR( "Failed to disable alpha to coverage" );
+ }
+
+ if( BSDsc.IndependentBlendEnable )
+ {
+ for( int i = 0; i < BSDsc.MaxRenderTargets; ++i )
+ {
+ const auto& RT = BSDsc.RenderTargets[i];
+ if( RT.BlendEnable )
+ {
+ glEnablei( GL_BLEND, i );
+ CHECK_GL_ERROR( "Failed to enable alpha blending" );
+
+ auto srcFactorRGB = BlendFactor2GLBlend( RT.SrcBlend );
+ auto dstFactorRGB = BlendFactor2GLBlend( RT.DestBlend );
+ auto srcFactorAlpha = BlendFactor2GLBlend( RT.SrcBlendAlpha );
+ auto dstFactorAlpha = BlendFactor2GLBlend( RT.DestBlendAlpha );
+ glBlendFuncSeparatei( i, srcFactorRGB, dstFactorRGB, srcFactorAlpha, dstFactorAlpha );
+ CHECK_GL_ERROR( "Failed to set blending factors" );
+
+ auto modeRGB = BlendOperation2GLBlendOp( RT.BlendOp );
+ auto modeAlpha = BlendOperation2GLBlendOp( RT.BlendOpAlpha );
+ glBlendEquationSeparatei( i, modeRGB, modeAlpha );
+ CHECK_GL_ERROR( "Failed to set blending equations" );
+ }
+ else
+ {
+ glDisablei( GL_BLEND, i );
+ CHECK_GL_ERROR( "Failed to disable alpha blending" );
+ }
+ }
+ }
+ else
+ {
+ const auto& RT0 = BSDsc.RenderTargets[0];
+ auto srcFactorRGB = BlendFactor2GLBlend( RT0.SrcBlend );
+ auto dstFactorRGB = BlendFactor2GLBlend( RT0.DestBlend );
+ auto srcFactorAlpha = BlendFactor2GLBlend( RT0.SrcBlendAlpha );
+ auto dstFactorAlpha = BlendFactor2GLBlend( RT0.DestBlendAlpha );
+ glBlendFuncSeparate( srcFactorRGB, dstFactorRGB, srcFactorAlpha, dstFactorAlpha );
+ CHECK_GL_ERROR( "Failed to set blending factors" );
+
+ auto modeRGB = BlendOperation2GLBlendOp( RT0.BlendOp );
+ auto modeAlpha = BlendOperation2GLBlendOp( RT0.BlendOpAlpha );
+ glBlendEquationSeparate( modeRGB, modeAlpha );
+ CHECK_GL_ERROR( "Failed to set blending equations" );
+ }
+ }
+ else
+ {
+ // Sets the blend disable flag for ALL color buffers.
+ glDisable( GL_BLEND );
+ CHECK_GL_ERROR( "Failed to disable alpha blending" );
+ }
+ }
+
+ void GLContextState::SetColorWriteMask( Uint32 RTIndex, Uint32 WriteMask, Bool bIsIndependent )
+ {
+ // Even though the write mask only applies to writes to a framebuffer, the mask state is NOT
+ // Framebuffer state. So it is NOT part of a Framebuffer Object or the Default Framebuffer.
+ // Binding a new framebuffer will NOT affect the mask.
+
+ if( !bIsIndependent )
+ RTIndex = 0;
+
+ if( m_ColorWriteMasks[RTIndex] != WriteMask ||
+ m_bIndependentWriteMasks != bIsIndependent )
+ {
+ if( bIsIndependent )
+ {
+ // Note that glColorMaski() does not set color mask for the framebuffer
+ // attachment point RTIndex. Rather it sets the mask for what was set
+ // by the glDrawBuffers() function for the i-th output
+ glColorMaski( RTIndex,
+ (WriteMask & COLOR_MASK_RED) ? GL_TRUE : GL_FALSE,
+ (WriteMask & COLOR_MASK_GREEN) ? GL_TRUE : GL_FALSE,
+ (WriteMask & COLOR_MASK_BLUE) ? GL_TRUE : GL_FALSE,
+ (WriteMask & COLOR_MASK_ALPHA) ? GL_TRUE : GL_FALSE );
+ CHECK_GL_ERROR( "Failed to set GL color mask" );
+
+ m_ColorWriteMasks[RTIndex] = WriteMask;
+ }
+ else
+ {
+ // glColorMask() sets the mask for ALL draw buffers
+ glColorMask( (WriteMask & COLOR_MASK_RED) ? GL_TRUE : GL_FALSE,
+ (WriteMask & COLOR_MASK_GREEN) ? GL_TRUE : GL_FALSE,
+ (WriteMask & COLOR_MASK_BLUE) ? GL_TRUE : GL_FALSE,
+ (WriteMask & COLOR_MASK_ALPHA) ? GL_TRUE : GL_FALSE );
+ CHECK_GL_ERROR( "Failed to set GL color mask" );
+
+ for( int rt = 0; rt < _countof( m_ColorWriteMasks ); ++rt )
+ m_ColorWriteMasks[rt] = WriteMask;
+ }
+ m_bIndependentWriteMasks = bIsIndependent;
+ }
+ }
+
+ void GLContextState::GetColorWriteMask( Uint32 RTIndex, Uint32 &WriteMask, Bool &bIsIndependent )
+ {
+ if( !m_bIndependentWriteMasks )
+ RTIndex = 0;
+ WriteMask = m_ColorWriteMasks[ RTIndex ];
+ bIsIndependent = m_bIndependentWriteMasks;
+ }
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/GLContextWindows.cpp b/Graphics/GraphicsEngineOpenGL/src/GLContextWindows.cpp
new file mode 100644
index 00000000..a0e7bf0b
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/GLContextWindows.cpp
@@ -0,0 +1,233 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "GLContextWindows.h"
+#include "DeviceCaps.h"
+#include "GLTypeConversions.h"
+
+namespace Diligent
+{
+
+ void APIENTRY openglCallbackFunction( GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar* message,
+ void* userParam )
+ {
+ std::stringstream MessageSS;
+
+ MessageSS << std::endl << "OPENGL DEBUG MESSAGE: " << message << std::endl;
+ MessageSS << "Type: ";
+ switch( type ) {
+ case GL_DEBUG_TYPE_ERROR:
+ MessageSS << "ERROR";
+ break;
+ case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+ MessageSS << "DEPRECATED_BEHAVIOR";
+ break;
+ case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+ MessageSS << "UNDEFINED_BEHAVIOR";
+ break;
+ case GL_DEBUG_TYPE_PORTABILITY:
+ MessageSS << "PORTABILITY";
+ break;
+ case GL_DEBUG_TYPE_PERFORMANCE:
+ MessageSS << "PERFORMANCE";
+ break;
+ case GL_DEBUG_TYPE_OTHER:
+ MessageSS << "OTHER";
+ break;
+ }
+ MessageSS << std::endl;
+
+ MessageSS << "Severity: ";
+ switch( severity ){
+ case GL_DEBUG_SEVERITY_LOW:
+ MessageSS << "LOW";
+ break;
+ case GL_DEBUG_SEVERITY_MEDIUM:
+ MessageSS << "MEDIUM";
+ break;
+ case GL_DEBUG_SEVERITY_HIGH:
+ MessageSS << "HIGH";
+ break;
+ }
+ MessageSS << std::endl;
+
+ //MessageSS << "Id: "<< id << std::endl;
+
+ OutputDebugStringA( MessageSS.str().c_str() );
+ }
+
+ GLContext::GLContext( const ContextInitInfo &Info, DeviceCaps &DeviceCaps ) :
+ m_SwapChainAttribs(Info.SwapChainAttribs),
+ m_Context(0),
+ m_WindowHandleToDeviceContext(0)
+ {
+ Int32 MajorVersion = 0, MinorVersion = 0;
+ if(Info.pNativeWndHandle != nullptr)
+ {
+ HWND hWnd = reinterpret_cast<HWND>(Info.pNativeWndHandle);
+ RECT rc;
+ GetClientRect( hWnd, &rc );
+ m_SwapChainAttribs.Width = rc.right - rc.left;
+ m_SwapChainAttribs.Height = rc.bottom - rc.top;
+
+ // See http://www.opengl.org/wiki/Tutorial:_OpenGL_3.1_The_First_Triangle_(C%2B%2B/Win)
+ // http://www.opengl.org/wiki/Creating_an_OpenGL_Context_(WGL)
+ PIXELFORMATDESCRIPTOR pfd;
+ memset( &pfd, 0, sizeof( PIXELFORMATDESCRIPTOR ) );
+ pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR );
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 32;
+ pfd.cDepthBits = 32;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+
+
+ m_WindowHandleToDeviceContext = GetDC( hWnd );
+ int nPixelFormat = ChoosePixelFormat( m_WindowHandleToDeviceContext, &pfd );
+
+ if( nPixelFormat == 0 )
+ LOG_ERROR_AND_THROW( "Invalid Pixel Format" );
+
+ BOOL bResult = SetPixelFormat( m_WindowHandleToDeviceContext, nPixelFormat, &pfd );
+ if( !bResult )
+ LOG_ERROR_AND_THROW( "Failed to set Pixel Format" );
+
+ // Create standard OpenGL (2.1) rendering context which will be used only temporarily,
+ HGLRC tempContext = wglCreateContext( m_WindowHandleToDeviceContext );
+ // and make it current
+ wglMakeCurrent( m_WindowHandleToDeviceContext, tempContext );
+
+ // Initialize GLEW
+ GLenum err = glewInit();
+ if( GLEW_OK != err )
+ LOG_ERROR_AND_THROW( "Failed to initialize GLEW" );
+
+
+ if( wglewIsSupported( "WGL_ARB_create_context" ) == 1 )
+ {
+ MajorVersion = 4;
+ MinorVersion = 2;
+ // Setup attributes for a new OpenGL 4.2 rendering context
+ int attribs[] =
+ {
+ WGL_CONTEXT_MAJOR_VERSION_ARB, MajorVersion,
+ WGL_CONTEXT_MINOR_VERSION_ARB, MinorVersion,
+ WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
+ GL_CONTEXT_PROFILE_MASK, GL_CONTEXT_CORE_PROFILE_BIT,
+ 0, 0
+ };
+
+ #ifdef _DEBUG
+ attribs[5] |= WGL_CONTEXT_DEBUG_BIT_ARB;
+ #endif
+
+ // Create new rendering context
+ // In order to create new OpenGL rendering context we have to call function wglCreateContextAttribsARB(),
+ // which is an OpenGL function and requires OpenGL to be active when it is called.
+ // The only way is to create an old context, activate it, and while it is active create a new one.
+ // Very inconsistent, but we have to live with it!
+ m_Context = wglCreateContextAttribsARB( m_WindowHandleToDeviceContext, 0, attribs );
+
+ // Delete tempContext
+ wglMakeCurrent( NULL, NULL );
+ wglDeleteContext( tempContext );
+ //
+ wglMakeCurrent( m_WindowHandleToDeviceContext, m_Context );
+ wglSwapIntervalEXT( 0 );
+ }
+ else
+ { //It's not possible to make a GL 3.x context. Use the old style context (GL 2.1 and before)
+ m_Context = tempContext;
+ }
+ }
+ else
+ {
+ auto CurrentCtx = wglGetCurrentContext();
+ m_WindowHandleToDeviceContext = wglGetCurrentDC();
+ if (CurrentCtx != 0)
+ {
+ LOG_INFO_MESSAGE("Attaching to existing OpenGL context")
+ }
+ else
+ {
+ LOG_ERROR_AND_THROW("No current GL context found! Provide non-null handle to a native Window to create a GL context")
+ }
+
+ // Initialize GLEW
+ GLenum err = glewInit();
+ if( GLEW_OK != err )
+ LOG_ERROR_AND_THROW( "Failed to initialize GLEW" );
+ }
+
+ //Checking GL version
+ const GLubyte *GLVersionString = glGetString( GL_VERSION );
+
+ //Or better yet, use the GL3 way to get the version number
+ glGetIntegerv( GL_MAJOR_VERSION, &MajorVersion );
+ glGetIntegerv( GL_MINOR_VERSION, &MinorVersion );
+
+ if( glDebugMessageCallback )
+ {
+ glEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS );
+ glDebugMessageCallback( openglCallbackFunction, nullptr );
+ GLuint unusedIds = 0;
+ glDebugMessageControl( GL_DONT_CARE,
+ GL_DONT_CARE,
+ GL_DONT_CARE,
+ 0,
+ &unusedIds,
+ true );
+ }
+ DeviceCaps.DevType = DeviceType::OpenGL;
+ DeviceCaps.MajorVersion = MajorVersion;
+ DeviceCaps.MinorVersion = MinorVersion;
+ bool IsGL43OrAbove = MajorVersion >= 5 || MajorVersion == 4 && MinorVersion >= 3;
+ auto &TexCaps = DeviceCaps.TexCaps;
+ TexCaps.bTexture2DMSSupported = IsGL43OrAbove;
+ TexCaps.bTexture2DMSArraySupported = IsGL43OrAbove;
+ TexCaps.bTextureViewSupported = IsGL43OrAbove;
+ }
+
+ GLContext::~GLContext()
+ {
+ // Do not destroy context if it was create by the app.
+ if( m_Context )
+ {
+ wglMakeCurrent( m_WindowHandleToDeviceContext, 0 );
+ wglDeleteContext( m_Context );
+ }
+ }
+
+ void GLContext::SwapBuffers()
+ {
+ ::SwapBuffers( m_WindowHandleToDeviceContext );
+ }
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/GLObjectWrapper.cpp b/Graphics/GraphicsEngineOpenGL/src/GLObjectWrapper.cpp
new file mode 100644
index 00000000..5793e469
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/GLObjectWrapper.cpp
@@ -0,0 +1,37 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "GLObjectWrapper.h"
+
+namespace GLObjectWrappers
+{
+ const char *GLBufferObjCreateReleaseHelper :: Name = "buffer";
+ const char *GLProgramObjCreateReleaseHelper :: Name = "program";
+ const char *GLShaderObjCreateReleaseHelper :: Name = "shader";
+ const char *GLPipelineObjCreateReleaseHelper:: Name = "piepline";
+ const char *GLVAOCreateReleaseHelper :: Name = "vertex array";
+ const char *GLTextureCreateReleaseHelper :: Name = "texture";
+ const char *GLSamplerCreateReleaseHelper :: Name = "sampler";
+ const char *GLFBOCreateReleaseHelper :: Name = "framebuffer";
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/GLProgram.cpp b/Graphics/GraphicsEngineOpenGL/src/GLProgram.cpp
new file mode 100644
index 00000000..808fcc12
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/GLProgram.cpp
@@ -0,0 +1,305 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "GLProgram.h"
+
+namespace Diligent
+{
+ GLProgram::GLProgram( bool CreateObject ) :
+ GLObjectWrappers::GLProgramObj( CreateObject )
+ {}
+
+ GLProgram::GLProgram( GLProgram&& Program ):
+ GLObjectWrappers::GLProgramObj( std::move( Program ) ),
+ m_UniformBlocks( std::move( Program.m_UniformBlocks ) ),
+ m_Samplers( std::move( Program.m_Samplers ) ),
+ m_Images( std::move( Program.m_Images ) ),
+ m_StorageBlocks( std::move( Program.m_StorageBlocks ) )
+ {}
+
+ void GLProgram::LoadUniforms()
+ {
+ GLuint GLProgram = static_cast<GLuint>(*this);
+
+ GLint numActiveUniforms = 0;
+ glGetProgramiv( GLProgram, GL_ACTIVE_UNIFORMS, &numActiveUniforms );
+ CHECK_GL_ERROR_AND_THROW( "Unable to get number of active uniforms\n" );
+
+ // Query the maximum name length of the active uniform (including null terminator)
+ GLint activeUniformMaxLength = 0;
+ glGetProgramiv( GLProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformMaxLength );
+ CHECK_GL_ERROR_AND_THROW( "Unable to get maximum uniform name length\n" );
+
+ GLint numActiveUniformBlocks = 0;
+ glGetProgramiv( GLProgram, GL_ACTIVE_UNIFORM_BLOCKS, &numActiveUniformBlocks );
+ CHECK_GL_ERROR_AND_THROW( "Unable to get the number of active uniform blocks\n" );
+
+ //
+ // #### This parameter is currently unsupported by Intel OGL drivers.
+ //
+ // Query the maximum name length of the active uniform block (including null terminator)
+ GLint activeUniformBlockMaxLength = 0;
+ // On Intel driver, this call might fail:
+ glGetProgramiv( GLProgram, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &activeUniformBlockMaxLength );
+ //CHECK_GL_ERROR_AND_THROW("Unable to get the maximum uniform block name length\n");
+ if( GL_NO_ERROR != glGetError() )
+ {
+ LOG_WARNING_MESSAGE( "Unable to get the maximum uniform block name length. Using 1024 as a workaround\n" );
+ activeUniformBlockMaxLength = 1024;
+ }
+
+
+ GLint numActiveShaderStorageBlocks = 0;
+ glGetProgramInterfaceiv( GLProgram, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &numActiveShaderStorageBlocks );
+ CHECK_GL_ERROR_AND_THROW( "Unable to get the number of shader storage blocks blocks\n" );
+
+ // Query the maximum name length of the active shader storage block (including null terminator)
+ GLint MaxShaderStorageBlockNameLen = 0;
+ glGetProgramInterfaceiv( GLProgram, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, &MaxShaderStorageBlockNameLen );
+ CHECK_GL_ERROR_AND_THROW( "Unable to get the maximum shader storage block name length\n" );
+
+ auto MaxNameLength = std::max( activeUniformMaxLength, activeUniformBlockMaxLength );
+ MaxNameLength = std::max( MaxNameLength, MaxShaderStorageBlockNameLen );
+
+ MaxNameLength = std::max( MaxNameLength, 512 );
+ std::vector<GLchar> Name( MaxNameLength + 1 );
+ for( int i = 0; i < numActiveUniforms; i++ )
+ {
+ GLenum dataType = 0;
+ GLint size = 0;
+ GLint NameLen = 0;
+ glGetActiveUniform( GLProgram, i, MaxNameLength, &NameLen, &size, &dataType, Name.data() );
+ CHECK_GL_ERROR_AND_THROW( "Unable to get active uniform\n" );
+ VERIFY( NameLen < MaxNameLength && NameLen == strlen( Name.data() ), "Incorrect uniform name" );
+ // Note that
+ // glGetActiveUniform( program, index, bufSize, length, size, type, name );
+ //
+ // is equivalent to
+ //
+ // const enum props[] = { ARRAY_SIZE, TYPE };
+ // glGetProgramResourceName( program, UNIFORM, index, bufSize, length, name );
+ // glGetProgramResourceiv( program, GL_UNIFORM, index, 1, &props[0], 1, NULL, size );
+ // glGetProgramResourceiv( program, GL_UNIFORM, index, 1, &props[1], 1, NULL, (int *)type );
+ //
+ // The latter is only available in GL 4.4 and GLES 3.1
+
+ switch( dataType )
+ {
+ case GL_SAMPLER_1D:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_1D_SHADOW:
+ case GL_SAMPLER_2D_SHADOW:
+
+ case GL_SAMPLER_1D_ARRAY:
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_1D_ARRAY_SHADOW:
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ case GL_SAMPLER_CUBE_SHADOW:
+
+ case GL_INT_SAMPLER_1D:
+ case GL_INT_SAMPLER_2D:
+ case GL_INT_SAMPLER_3D:
+ case GL_INT_SAMPLER_CUBE:
+ case GL_INT_SAMPLER_1D_ARRAY:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_1D:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+
+ case GL_SAMPLER_CUBE_MAP_ARRAY:
+ case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
+ case GL_INT_SAMPLER_CUBE_MAP_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY:
+
+ case GL_SAMPLER_2D_MULTISAMPLE:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+
+ case GL_SAMPLER_BUFFER:
+ case GL_INT_SAMPLER_BUFFER:
+ case GL_UNSIGNED_INT_SAMPLER_BUFFER:
+ {
+ auto UniformLocation = glGetUniformLocation( GLProgram, Name.data() );
+ // Note that glGetUniformLocation(program, name) is equivalent to
+ // glGetProgramResourceLocation( program, GL_UNIFORM, name );
+ // The latter is only available in GL 4.4 and GLES 3.1
+ m_Samplers.emplace_back( SamplerInfo( Name.data(), UniformLocation, dataType) );
+ break;
+ }
+
+ case GL_IMAGE_1D:
+ case GL_IMAGE_2D:
+ case GL_IMAGE_3D:
+ case GL_IMAGE_2D_RECT:
+ case GL_IMAGE_CUBE:
+ case GL_IMAGE_BUFFER:
+ case GL_IMAGE_1D_ARRAY:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_IMAGE_CUBE_MAP_ARRAY:
+ case GL_IMAGE_2D_MULTISAMPLE:
+ case GL_IMAGE_2D_MULTISAMPLE_ARRAY:
+ case GL_INT_IMAGE_1D:
+ case GL_INT_IMAGE_2D:
+ case GL_INT_IMAGE_3D:
+ case GL_INT_IMAGE_2D_RECT:
+ case GL_INT_IMAGE_CUBE:
+ case GL_INT_IMAGE_BUFFER:
+ case GL_INT_IMAGE_1D_ARRAY:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_CUBE_MAP_ARRAY:
+ case GL_INT_IMAGE_2D_MULTISAMPLE:
+ case GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_1D:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_2D_RECT:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_BUFFER:
+ case GL_UNSIGNED_INT_IMAGE_1D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE:
+ case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
+ {
+ auto UniformLocation = glGetUniformLocation( GLProgram, Name.data() );
+
+ GLint BindingPoint = -1;
+ // The value of an image uniform is an integer specifying the image unit accessed
+ glGetUniformiv( GLProgram, UniformLocation, &BindingPoint );
+ CHECK_GL_ERROR_AND_THROW("Failed to get image binding point");
+ VERIFY( BindingPoint >= 0, "Incorrect binding point" );
+
+ m_Images.emplace_back( ImageInfo(Name.data(), BindingPoint, dataType) );
+ break;
+ }
+
+ default:
+ // Some other uniform type like scalar, matrix etc.
+ break;
+ }
+ }
+
+ for( int i = 0; i < numActiveUniformBlocks; i++ )
+ {
+ GLsizei NameLen = 0;
+ glGetActiveUniformBlockName( GLProgram, i, MaxNameLength, &NameLen, Name.data() );
+ CHECK_GL_ERROR_AND_THROW( "Unable to get active uniform block name\n" );
+ VERIFY( NameLen < MaxNameLength && NameLen == strlen( Name.data() ), "Incorrect uniform block name" );
+
+ // glGetActiveUniformBlockName( program, uniformBlockIndex, bufSize, length, uniformBlockName );
+ // is equivalent to
+ // glGetProgramResourceName(program, GL_UNIFORM_BLOCK, uniformBlockIndex, bufSize, length, uniformBlockName);
+
+ auto UniformBlockIndex = glGetUniformBlockIndex( GLProgram, Name.data() );
+ CHECK_GL_ERROR_AND_THROW( "Unable to get active uniform block index\n" );
+ // glGetUniformBlockIndex( program, uniformBlockName );
+ // is equivalent to
+ // glGetProgramResourceIndex( program, GL_UNIFORM_BLOCK, uniformBlockName );
+ m_UniformBlocks.emplace_back(UniformBufferInfo(Name.data(), UniformBlockIndex));
+ }
+
+ for( int i = 0; i < numActiveShaderStorageBlocks; ++i )
+ {
+ GLsizei Length = 0;
+ glGetProgramResourceName( GLProgram, GL_SHADER_STORAGE_BLOCK, i, MaxNameLength, &Length, Name.data() );
+ CHECK_GL_ERROR_AND_THROW( "Unable to get shader storage block name\n" );
+ VERIFY( Length < MaxNameLength && Length == strlen( Name.data() ), "Incorrect shader storage block name" );
+
+ GLenum Prop = GL_BUFFER_BINDING;
+ GLint Binding = -1;
+ GLint ValuesWritten = 0;
+ glGetProgramResourceiv( GLProgram, GL_SHADER_STORAGE_BLOCK, i, 1, &Prop, 1, &ValuesWritten, &Binding );
+ CHECK_GL_ERROR_AND_THROW( "Unable to get shader storage block binding\n" );
+ VERIFY( ValuesWritten == 1 && Binding >= 0, "Incorrect shader storage block binding" );
+
+ m_StorageBlocks.emplace_back( StorageBlockInfo(Name.data(), Binding) );
+ }
+ }
+
+ template<typename TResArrayType>
+ void BindResourcesHelper(TResArrayType &ResArr, IResourceMapping *pResourceMapping, Uint32 Flags)
+ {
+ for( auto res = ResArr.begin(); res != ResArr.end(); ++res )
+ {
+ auto &Name = res->Name;
+ if( Flags & BIND_SHADER_RESOURCES_RESET_BINDINGS )
+ res->pResource.Release();
+
+ if( (Flags & BIND_SHADER_RESOURCES_UPDATE_UNRESOLVED) && res->pResource )
+ continue; // Skip already resolved resources
+
+ RefCntAutoPtr<IDeviceObject> pNewRes;
+ pResourceMapping->GetResource( Name.c_str(), static_cast<IDeviceObject**>(&pNewRes) );
+
+ if( !pNewRes )
+ {
+ if( Flags & BIND_SHADER_RESOURCES_ALL_RESOLVED )
+ LOG_ERROR_MESSAGE( "Resource \"", Name, "\" is not found in the resource mapping" );
+ continue;
+ }
+ res->pResource = pNewRes;
+ }
+ }
+
+ void GLProgram::BindResources( IResourceMapping *pResourceMapping, Uint32 Flags )
+ {
+ if( !pResourceMapping )
+ return;
+
+ BindResourcesHelper( m_UniformBlocks, pResourceMapping, Flags );
+ BindResourcesHelper( m_Samplers, pResourceMapping, Flags );
+ BindResourcesHelper( m_Images, pResourceMapping, Flags );
+ BindResourcesHelper( m_StorageBlocks, pResourceMapping, Flags );
+ }
+
+#ifdef VERIFY_RESOURCE_BINDINGS
+ template<typename TResArrayType>
+ void dbgVerifyResourceBindingsHelper(TResArrayType &ResArr, const Char *VarType)
+ {
+ for( auto res = ResArr.begin(); res != ResArr.end(); ++res )
+ {
+ auto &Name = res->Name;
+ if( !res->pResource )
+ LOG_ERROR_MESSAGE( "No resource is bound to ", VarType, " variable \"", res->Name, "\"" );
+ }
+ }
+
+ void GLProgram::dbgVerifyResourceBindings()
+ {
+ dbgVerifyResourceBindingsHelper( m_UniformBlocks, "uniform block" );
+ dbgVerifyResourceBindingsHelper( m_Samplers, "sampler" );
+ dbgVerifyResourceBindingsHelper( m_Images, "image" );
+ dbgVerifyResourceBindingsHelper( m_StorageBlocks, "shader storage block" );
+ }
+#endif
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/GLStubs.cpp b/Graphics/GraphicsEngineOpenGL/src/GLStubs.cpp
new file mode 100644
index 00000000..d200bc33
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/GLStubs.cpp
@@ -0,0 +1,266 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "GLStubs.h"
+#include <EGL/egl.h>
+
+#define DECLARE_GL_FUNCTION(Func, FuncType, ...)\
+ FuncType Func = nullptr; \
+ void Func##Stub(__VA_ARGS__) \
+ { \
+ UnsupportedGLFunctionStub(#Func); \
+ }
+
+#ifdef LOAD_GL_BIND_IMAGE_TEXTURE
+ DECLARE_GL_FUNCTION( glBindImageTexture, PFNGLBINDIMAGETEXTUREPROC, GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format )
+#endif
+
+#ifdef LOAD_GL_DISPATCH_COMPUTE
+ DECLARE_GL_FUNCTION( glDispatchCompute, PFNGLDISPATCHCOMPUTEPROC, GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z )
+#endif
+
+#ifdef LOAD_GL_PROGRAM_UNIFORM_1I
+ DECLARE_GL_FUNCTION( glProgramUniform1i, PFNGLPROGRAMUNIFORM1IPROC, GLuint program, GLint location, GLint x )
+#endif
+
+#ifdef LOAD_GL_MEMORY_BARRIER
+ DECLARE_GL_FUNCTION( glMemoryBarrier, PFNGLMEMORYBARRIERPROC, GLbitfield barriers )
+#endif
+
+#ifdef LOAD_DRAW_ELEMENTS_INDIRECT
+ DECLARE_GL_FUNCTION( glDrawElementsIndirect, PFNGLDRAWELEMENTSINDIRECTPROC, GLenum mode, GLenum type, const GLvoid *indirect )
+#endif
+
+#ifdef LOAD_DRAW_ARRAYS_INDIRECT
+ DECLARE_GL_FUNCTION( glDrawArraysIndirect, PFNGLDRAWARRAYSINDIRECTPROC, GLenum mode, const GLvoid *indirect )
+#endif
+
+#ifdef LOAD_GEN_PROGRAM_PIPELINES
+ DECLARE_GL_FUNCTION( glGenProgramPipelines, PFNGLGENPROGRAMPIPELINESPROC, GLsizei n, GLuint* pipelines )
+#endif
+
+#ifdef LOAD_GL_DELETE_PROGRAM_PIPELINES
+ DECLARE_GL_FUNCTION( glDeleteProgramPipelines, PFNGLDELETEPROGRAMPIPELINESPROC, GLsizei n, const GLuint* pipelines )
+#endif
+
+#ifdef LOAD_GL_BIND_PROGRAM_PIPELINE
+ DECLARE_GL_FUNCTION( glBindProgramPipeline, PFNGLBINDPROGRAMPIPELINEPROC, GLuint pipeline )
+#endif
+
+#ifdef LOAD_GL_USE_PROGRAM_STAGES
+ DECLARE_GL_FUNCTION( glUseProgramStages, PFNGLUSEPROGRAMSTAGESPROC, GLuint pipeline, GLbitfield stages, GLuint program )
+#endif
+
+#ifdef LOAD_GL_TEX_STORAGE_2D_MULTISAMPLE
+ DECLARE_GL_FUNCTION( glTexStorage2DMultisample, PFNGLTEXSTORAGE2DMULTISAMPLEPROC, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations )
+#endif
+
+#ifdef LOAD_GL_GET_PROGRAM_INTERFACEIV
+ DECLARE_GL_FUNCTION( glGetProgramInterfaceiv, PFNGLGETPROGRAMINTERFACEIVPROC, GLuint program, GLenum programInterface, GLenum pname, GLint* params )
+#endif
+
+#ifdef LOAD_GL_GET_PROGRAM_RESOURCE_NAME
+ DECLARE_GL_FUNCTION( glGetProgramResourceName, PFNGLGETPROGRAMRESOURCENAMEPROC, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, GLchar *name )
+#endif
+
+#ifdef LOAD_GL_GET_PROGRAM_RESOURCEIV
+ DECLARE_GL_FUNCTION( glGetProgramResourceiv, PFNGLGETPROGRAMRESOURCEIVPROC, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum* props, GLsizei bufSize, GLsizei *length, GLint *params )
+#endif
+
+#ifdef LOAD_DISPATCH_COMPUTE_INDIRECT
+ DECLARE_GL_FUNCTION( glDispatchComputeIndirect, PFNGLDISPATCHCOMPUTEINDIRECTPROC, GLintptr indirect )
+#endif
+
+#ifdef LOAD_GL_TEX_BUFFER
+ DECLARE_GL_FUNCTION( glTexBuffer, PFNGLTEXBUFFERPROC, GLenum, GLenum, GLuint)
+#endif
+
+#ifdef LOAD_GL_POLYGON_MODE
+ DECLARE_GL_FUNCTION( glPolygonMode, PFNGLPOLYGONMODE, GLenum, GLenum)
+#endif
+
+#ifdef LOAD_GL_ENABLEI
+ DECLARE_GL_FUNCTION( glEnablei, PFNGLENABLEIPROC, GLenum, GLuint)
+#endif
+
+#ifdef LOAD_GL_BLEND_FUNC_SEPARATEI
+ DECLARE_GL_FUNCTION( glBlendFuncSeparatei, PFNGLBLENDFUNCSEPARATEIPROC, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+#endif
+
+#ifdef LOAD_GL_BLEND_EQUATION_SEPARATEI
+ DECLARE_GL_FUNCTION( glBlendEquationSeparatei, PFNGLBLENDEQUATIONSEPARATEIPROC, GLuint buf, GLenum modeRGB, GLenum modeAlpha)
+#endif
+
+#ifdef LOAD_GL_DISABLEI
+ DECLARE_GL_FUNCTION( glDisablei, PFNGLDISABLEIPROC, GLenum, GLuint)
+#endif
+
+#ifdef LOAD_GL_COLOR_MASKI
+ DECLARE_GL_FUNCTION( glColorMaski, PFNGLCOLORMASKIPROC, GLuint, GLboolean, GLboolean, GLboolean, GLboolean)
+#endif
+
+#ifdef LOAD_GL_VIEWPORT_INDEXEDF
+ DECLARE_GL_FUNCTION( glViewportIndexedf, PFNGLVIEWPORTINDEXEDFPROC, GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h)
+#endif
+
+#ifdef LOAD_GL_SCISSOR_INDEXED
+ DECLARE_GL_FUNCTION( glScissorIndexed, PFNGLSCISSORINDEXEDPROC, GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height)
+#endif
+
+#ifdef LOAD_GL_FRAMEBUFFER_TEXTURE
+ DECLARE_GL_FUNCTION( glFramebufferTexture, PFNGLFRAMEBUFFERTEXTUREPROC, GLenum, GLenum, GLuint, GLint)
+#endif
+
+#ifdef LOAD_GL_FRAMEBUFFER_TEXTURE_1D
+ DECLARE_GL_FUNCTION( glFramebufferTexture1D, PFNGLFRAMEBUFFERTEXTURE1DPROC, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+#endif
+
+#ifdef LOAD_GL_FRAMEBUFFER_TEXTURE_3D
+ DECLARE_GL_FUNCTION( glFramebufferTexture3D, PFNGLFRAMEBUFFERTEXTURE3DPROC, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer )
+#endif
+
+#ifdef LOAD_GL_COPY_IMAGE_SUB_DATA
+ DECLARE_GL_FUNCTION( glCopyImageSubData, PFNGLCOPYIMAGESUBDATAPROC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth )
+#endif
+
+void LoadGLFunctions()
+{
+
+#define LOAD_GL_FUNCTION(Func, FuncType)\
+Func = (FuncType)eglGetProcAddress( #Func );\
+ if( !Func )Func = Func##Stub;
+
+#ifdef LOAD_GL_BIND_IMAGE_TEXTURE
+ LOAD_GL_FUNCTION( glBindImageTexture, PFNGLBINDIMAGETEXTUREPROC )
+#endif
+
+#ifdef LOAD_GL_DISPATCH_COMPUTE
+ LOAD_GL_FUNCTION( glDispatchCompute, PFNGLDISPATCHCOMPUTEPROC )
+#endif
+
+#ifdef LOAD_GEN_PROGRAM_PIPELINES
+ LOAD_GL_FUNCTION( glGenProgramPipelines, PFNGLGENPROGRAMPIPELINESPROC )
+#endif
+
+#ifdef LOAD_GL_DELETE_PROGRAM_PIPELINES
+ LOAD_GL_FUNCTION( glDeleteProgramPipelines, PFNGLDELETEPROGRAMPIPELINESPROC )
+#endif
+
+#ifdef LOAD_GL_BIND_PROGRAM_PIPELINE
+ LOAD_GL_FUNCTION( glBindProgramPipeline, PFNGLBINDPROGRAMPIPELINEPROC )
+#endif
+
+#ifdef LOAD_GL_USE_PROGRAM_STAGES
+ LOAD_GL_FUNCTION( glUseProgramStages, PFNGLUSEPROGRAMSTAGESPROC )
+#endif
+
+#ifdef LOAD_GL_PROGRAM_UNIFORM_1I
+ LOAD_GL_FUNCTION( glProgramUniform1i, PFNGLPROGRAMUNIFORM1IPROC )
+#endif
+
+#ifdef LOAD_GL_MEMORY_BARRIER
+ LOAD_GL_FUNCTION( glMemoryBarrier, PFNGLMEMORYBARRIERPROC )
+#endif
+
+#ifdef LOAD_DRAW_ELEMENTS_INDIRECT
+ LOAD_GL_FUNCTION( glDrawElementsIndirect, PFNGLDRAWELEMENTSINDIRECTPROC )
+#endif
+
+#ifdef LOAD_DRAW_ARRAYS_INDIRECT
+ LOAD_GL_FUNCTION( glDrawArraysIndirect, PFNGLDRAWARRAYSINDIRECTPROC )
+#endif
+
+#ifdef LOAD_GL_TEX_STORAGE_2D_MULTISAMPLE
+ LOAD_GL_FUNCTION( glTexStorage2DMultisample, PFNGLTEXSTORAGE2DMULTISAMPLEPROC )
+#endif
+
+#ifdef LOAD_GL_GET_PROGRAM_INTERFACEIV
+ LOAD_GL_FUNCTION( glGetProgramInterfaceiv, PFNGLGETPROGRAMINTERFACEIVPROC )
+#endif
+
+#ifdef LOAD_GL_GET_PROGRAM_RESOURCE_NAME
+ LOAD_GL_FUNCTION( glGetProgramResourceName, PFNGLGETPROGRAMRESOURCENAMEPROC )
+#endif
+
+#ifdef LOAD_GL_GET_PROGRAM_RESOURCEIV
+ LOAD_GL_FUNCTION( glGetProgramResourceiv, PFNGLGETPROGRAMRESOURCEIVPROC )
+#endif
+
+#ifdef LOAD_DISPATCH_COMPUTE_INDIRECT
+ LOAD_GL_FUNCTION( glDispatchComputeIndirect, PFNGLDISPATCHCOMPUTEINDIRECTPROC )
+#endif
+
+#ifdef LOAD_GL_TEX_BUFFER
+ LOAD_GL_FUNCTION( glTexBuffer, PFNGLTEXBUFFERPROC )
+#endif
+
+#ifdef LOAD_GL_POLYGON_MODE
+ LOAD_GL_FUNCTION( glPolygonMode, PFNGLPOLYGONMODE)
+#endif
+
+#ifdef LOAD_GL_ENABLEI
+ LOAD_GL_FUNCTION( glEnablei, PFNGLENABLEIPROC)
+#endif
+
+#ifdef LOAD_GL_BLEND_FUNC_SEPARATEI
+ LOAD_GL_FUNCTION( glBlendFuncSeparatei, PFNGLBLENDFUNCSEPARATEIPROC )
+#endif
+
+#ifdef LOAD_GL_BLEND_EQUATION_SEPARATEI
+ LOAD_GL_FUNCTION( glBlendEquationSeparatei, PFNGLBLENDEQUATIONSEPARATEIPROC )
+#endif
+
+#ifdef LOAD_GL_DISABLEI
+ LOAD_GL_FUNCTION( glDisablei, PFNGLDISABLEIPROC )
+#endif
+
+#ifdef LOAD_GL_COLOR_MASKI
+ LOAD_GL_FUNCTION( glColorMaski, PFNGLCOLORMASKIPROC )
+#endif
+
+#ifdef LOAD_GL_VIEWPORT_INDEXEDF
+ LOAD_GL_FUNCTION( glViewportIndexedf, PFNGLVIEWPORTINDEXEDFPROC )
+#endif
+
+#ifdef LOAD_GL_SCISSOR_INDEXED
+ LOAD_GL_FUNCTION( glScissorIndexed, PFNGLSCISSORINDEXEDPROC )
+#endif
+
+#ifdef LOAD_GL_FRAMEBUFFER_TEXTURE
+ LOAD_GL_FUNCTION( glFramebufferTexture, PFNGLFRAMEBUFFERTEXTUREPROC )
+#endif
+
+#ifdef LOAD_GL_FRAMEBUFFER_TEXTURE_1D
+ LOAD_GL_FUNCTION( glFramebufferTexture1D, PFNGLFRAMEBUFFERTEXTURE1DPROC )
+#endif
+
+#ifdef LOAD_GL_FRAMEBUFFER_TEXTURE_3D
+ LOAD_GL_FUNCTION( glFramebufferTexture3D, PFNGLFRAMEBUFFERTEXTURE3DPROC )
+#endif
+
+#ifdef LOAD_GL_COPY_IMAGE_SUB_DATA
+ // Do not use proxy if function is not available!
+ glCopyImageSubData = (PFNGLCOPYIMAGESUBDATAPROC)eglGetProcAddress( "glCopyImageSubData" );
+#endif
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/GLTypeConversions.cpp b/Graphics/GraphicsEngineOpenGL/src/GLTypeConversions.cpp
new file mode 100644
index 00000000..27e3e81a
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/GLTypeConversions.cpp
@@ -0,0 +1,602 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "GLTypeConversions.h"
+
+namespace Diligent
+{
+
+
+GLenum TexFormatToGLInternalTexFormat(TEXTURE_FORMAT TexFormat, Uint32 BindFlags)
+{
+ static Bool bFormatMapIntialized = false;
+ static GLenum FmtToGLFmtMap[TEX_FORMAT_NUM_FORMATS] = {0};
+ if( !bFormatMapIntialized )
+ {
+ // http://www.opengl.org/wiki/Image_Format
+ FmtToGLFmtMap[ TEX_FORMAT_UNKNOWN ] = 0;
+
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA32_TYPELESS ] = GL_RGBA32F;
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA32_FLOAT ] = GL_RGBA32F;
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA32_UINT ] = GL_RGBA32UI;
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA32_SINT ] = GL_RGBA32I;
+
+ FmtToGLFmtMap[ TEX_FORMAT_RGB32_TYPELESS ] = GL_RGB32F;
+ FmtToGLFmtMap[ TEX_FORMAT_RGB32_FLOAT ] = GL_RGB32F;
+ FmtToGLFmtMap[ TEX_FORMAT_RGB32_UINT ] = GL_RGB32UI;
+ FmtToGLFmtMap[ TEX_FORMAT_RGB32_SINT ] = GL_RGB32I;
+
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA16_TYPELESS ] = GL_RGBA16F;
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA16_FLOAT ] = GL_RGBA16F;
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA16_UNORM ] = GL_RGBA16;
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA16_UINT ] = GL_RGBA16UI;
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA16_SNORM ] = GL_RGBA16_SNORM;
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA16_SINT ] = GL_RGBA16I;
+
+ FmtToGLFmtMap[ TEX_FORMAT_RG32_TYPELESS ] = GL_RG32F;
+ FmtToGLFmtMap[ TEX_FORMAT_RG32_FLOAT ] = GL_RG32F;
+ FmtToGLFmtMap[ TEX_FORMAT_RG32_UINT ] = GL_RG32UI;
+ FmtToGLFmtMap[ TEX_FORMAT_RG32_SINT ] = GL_RG32I;
+
+ FmtToGLFmtMap[ TEX_FORMAT_R32G8X24_TYPELESS ] = GL_DEPTH32F_STENCIL8;
+ FmtToGLFmtMap[ TEX_FORMAT_D32_FLOAT_S8X24_UINT ] = GL_DEPTH32F_STENCIL8;
+ FmtToGLFmtMap[ TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS ]=GL_DEPTH32F_STENCIL8;
+ FmtToGLFmtMap[ TEX_FORMAT_X32_TYPELESS_G8X24_UINT ]= 0;//GL_DEPTH32F_STENCIL8;
+
+ FmtToGLFmtMap[ TEX_FORMAT_RGB10A2_TYPELESS ] = GL_RGB10_A2;
+ FmtToGLFmtMap[ TEX_FORMAT_RGB10A2_UNORM ] = GL_RGB10_A2;
+ FmtToGLFmtMap[ TEX_FORMAT_RGB10A2_UINT ] = GL_RGB10_A2UI;
+ FmtToGLFmtMap[ TEX_FORMAT_R11G11B10_FLOAT ] = GL_R11F_G11F_B10F;
+
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA8_TYPELESS ] = GL_RGBA8;
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA8_UNORM ] = GL_RGBA8;
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA8_UNORM_SRGB ] = GL_SRGB8_ALPHA8;
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA8_UINT ] = GL_RGBA8UI;
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA8_SNORM ] = GL_RGBA8_SNORM;
+ FmtToGLFmtMap[ TEX_FORMAT_RGBA8_SINT ] = GL_RGBA8I;
+
+ FmtToGLFmtMap[ TEX_FORMAT_RG16_TYPELESS ] = GL_RG16F;
+ FmtToGLFmtMap[ TEX_FORMAT_RG16_FLOAT ] = GL_RG16F;
+ FmtToGLFmtMap[ TEX_FORMAT_RG16_UNORM ] = GL_RG16;
+ FmtToGLFmtMap[ TEX_FORMAT_RG16_UINT ] = GL_RG16UI;
+ FmtToGLFmtMap[ TEX_FORMAT_RG16_SNORM ] = GL_RG16_SNORM;
+ FmtToGLFmtMap[ TEX_FORMAT_RG16_SINT ] = GL_RG16I;
+
+ FmtToGLFmtMap[ TEX_FORMAT_R32_TYPELESS ] = GL_R32F;
+ FmtToGLFmtMap[ TEX_FORMAT_D32_FLOAT ] = GL_DEPTH_COMPONENT32F;
+ FmtToGLFmtMap[ TEX_FORMAT_R32_FLOAT ] = GL_R32F;
+ FmtToGLFmtMap[ TEX_FORMAT_R32_UINT ] = GL_R32UI;
+ FmtToGLFmtMap[ TEX_FORMAT_R32_SINT ] = GL_R32I;
+
+ FmtToGLFmtMap[ TEX_FORMAT_R24G8_TYPELESS ] = GL_DEPTH24_STENCIL8;
+ FmtToGLFmtMap[ TEX_FORMAT_D24_UNORM_S8_UINT ] = GL_DEPTH24_STENCIL8;
+ FmtToGLFmtMap[ TEX_FORMAT_R24_UNORM_X8_TYPELESS ] = GL_DEPTH24_STENCIL8;
+ FmtToGLFmtMap[ TEX_FORMAT_X24_TYPELESS_G8_UINT ] = 0;//GL_DEPTH24_STENCIL8;
+
+ FmtToGLFmtMap[ TEX_FORMAT_RG8_TYPELESS ] = GL_RG8;
+ FmtToGLFmtMap[ TEX_FORMAT_RG8_UNORM ] = GL_RG8;
+ FmtToGLFmtMap[ TEX_FORMAT_RG8_UINT ] = GL_RG8UI;
+ FmtToGLFmtMap[ TEX_FORMAT_RG8_SNORM ] = GL_RG8_SNORM;
+ FmtToGLFmtMap[ TEX_FORMAT_RG8_SINT ] = GL_RG8I;
+
+ FmtToGLFmtMap[ TEX_FORMAT_R16_TYPELESS ] = GL_R16F;
+ FmtToGLFmtMap[ TEX_FORMAT_R16_FLOAT ] = GL_R16F;
+ FmtToGLFmtMap[ TEX_FORMAT_D16_UNORM ] = GL_DEPTH_COMPONENT16;
+ FmtToGLFmtMap[ TEX_FORMAT_R16_UNORM ] = GL_R16;
+ FmtToGLFmtMap[ TEX_FORMAT_R16_UINT ] = GL_R16UI;
+ FmtToGLFmtMap[ TEX_FORMAT_R16_SNORM ] = GL_R16_SNORM;
+ FmtToGLFmtMap[ TEX_FORMAT_R16_SINT ] = GL_R16I;
+
+ FmtToGLFmtMap[ TEX_FORMAT_R8_TYPELESS ] = GL_R8;
+ FmtToGLFmtMap[ TEX_FORMAT_R8_UNORM ] = GL_R8;
+ FmtToGLFmtMap[ TEX_FORMAT_R8_UINT ] = GL_R8UI;
+ FmtToGLFmtMap[ TEX_FORMAT_R8_SNORM ] = GL_R8_SNORM;
+ FmtToGLFmtMap[ TEX_FORMAT_R8_SINT ] = GL_R8I;
+ FmtToGLFmtMap[ TEX_FORMAT_A8_UNORM ] = 0;
+
+ FmtToGLFmtMap[ TEX_FORMAT_R1_UNORM ] = 0;
+
+ FmtToGLFmtMap[ TEX_FORMAT_RGB9E5_SHAREDEXP ] = GL_RGB9_E5;
+ FmtToGLFmtMap[ TEX_FORMAT_RG8_B8G8_UNORM ] = 0;
+ FmtToGLFmtMap[ TEX_FORMAT_G8R8_G8B8_UNORM ] = 0;
+
+ // http://www.g-truc.net/post-0335.html
+ // http://renderingpipeline.com/2012/07/texture-compression/
+ FmtToGLFmtMap[ TEX_FORMAT_BC1_TYPELESS ] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ FmtToGLFmtMap[ TEX_FORMAT_BC1_UNORM ] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ FmtToGLFmtMap[ TEX_FORMAT_BC1_UNORM_SRGB ] = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+ FmtToGLFmtMap[ TEX_FORMAT_BC2_TYPELESS ] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ FmtToGLFmtMap[ TEX_FORMAT_BC2_UNORM ] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ FmtToGLFmtMap[ TEX_FORMAT_BC2_UNORM_SRGB ] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+ FmtToGLFmtMap[ TEX_FORMAT_BC3_TYPELESS ] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ FmtToGLFmtMap[ TEX_FORMAT_BC3_UNORM ] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ FmtToGLFmtMap[ TEX_FORMAT_BC3_UNORM_SRGB ] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+ FmtToGLFmtMap[ TEX_FORMAT_BC4_TYPELESS ] = GL_COMPRESSED_RED_RGTC1;
+ FmtToGLFmtMap[ TEX_FORMAT_BC4_UNORM ] = GL_COMPRESSED_RED_RGTC1;
+ FmtToGLFmtMap[ TEX_FORMAT_BC4_SNORM ] = GL_COMPRESSED_SIGNED_RED_RGTC1;
+ FmtToGLFmtMap[ TEX_FORMAT_BC5_TYPELESS ] = GL_COMPRESSED_RG_RGTC2;
+ FmtToGLFmtMap[ TEX_FORMAT_BC5_UNORM ] = GL_COMPRESSED_RG_RGTC2;
+ FmtToGLFmtMap[ TEX_FORMAT_BC5_SNORM ] = GL_COMPRESSED_SIGNED_RG_RGTC2;
+ FmtToGLFmtMap[ TEX_FORMAT_B5G6R5_UNORM ] = 0;
+ FmtToGLFmtMap[ TEX_FORMAT_B5G5R5A1_UNORM ] = 0;
+ FmtToGLFmtMap[ TEX_FORMAT_BGRA8_UNORM ] = 0;
+ FmtToGLFmtMap[ TEX_FORMAT_BGRX8_UNORM ] = 0;
+ FmtToGLFmtMap[ TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM ] = 0;
+ FmtToGLFmtMap[ TEX_FORMAT_BGRA8_TYPELESS ] = 0;
+ FmtToGLFmtMap[ TEX_FORMAT_BGRA8_UNORM_SRGB ] = 0;
+ FmtToGLFmtMap[ TEX_FORMAT_BGRX8_TYPELESS ] = 0;
+ FmtToGLFmtMap[ TEX_FORMAT_BGRX8_UNORM_SRGB ] = 0;
+ FmtToGLFmtMap[ TEX_FORMAT_BC6H_TYPELESS ] = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
+ FmtToGLFmtMap[ TEX_FORMAT_BC6H_UF16 ] = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
+ FmtToGLFmtMap[ TEX_FORMAT_BC6H_SF16 ] = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
+ FmtToGLFmtMap[ TEX_FORMAT_BC7_TYPELESS ] = GL_COMPRESSED_RGBA_BPTC_UNORM;
+ FmtToGLFmtMap[ TEX_FORMAT_BC7_UNORM ] = GL_COMPRESSED_RGBA_BPTC_UNORM;
+ FmtToGLFmtMap[ TEX_FORMAT_BC7_UNORM_SRGB ] = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
+
+ bFormatMapIntialized = true;
+ }
+
+ if( TexFormat >= TEX_FORMAT_UNKNOWN && TexFormat < TEX_FORMAT_NUM_FORMATS )
+ {
+ auto GLFormat = FmtToGLFmtMap[TexFormat];
+ if( BindFlags != 0 )
+ GLFormat = CorrectGLTexFormat( GLFormat, BindFlags );
+ return GLFormat;
+ }
+ else
+ {
+ UNEXPECTED( "Texture format (", TexFormat, ") out of allowed range [0, ", TEX_FORMAT_NUM_FORMATS-1, "]" );
+ return 0;
+ }
+}
+
+GLenum CorrectGLTexFormat( GLenum GLTexFormat, Uint32 BindFlags )
+{
+ if( BindFlags & BIND_DEPTH_STENCIL )
+ {
+ if( GLTexFormat == GL_R32F )
+ GLTexFormat = GL_DEPTH_COMPONENT32F;
+ if( GLTexFormat == GL_R16 )
+ GLTexFormat = GL_DEPTH_COMPONENT16;
+ }
+ return GLTexFormat;
+}
+
+NativePixelAttribs GetNativePixelTransferAttribs(TEXTURE_FORMAT TexFormat)
+{
+ // http://www.opengl.org/wiki/Pixel_Transfer
+
+ static Bool bAttribsMapIntialized = false;
+ static NativePixelAttribs FmtToGLPixelFmt[TEX_FORMAT_NUM_FORMATS];
+ if( !bAttribsMapIntialized)
+ {
+ // http://www.opengl.org/wiki/Image_Format
+ FmtToGLPixelFmt[ TEX_FORMAT_UNKNOWN ] = NativePixelAttribs();
+
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA32_TYPELESS ] = NativePixelAttribs(GL_RGBA, GL_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA32_FLOAT ] = NativePixelAttribs(GL_RGBA, GL_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA32_UINT ] = NativePixelAttribs(GL_RGBA_INTEGER, GL_UNSIGNED_INT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA32_SINT ] = NativePixelAttribs(GL_RGBA_INTEGER, GL_INT);
+
+ FmtToGLPixelFmt[ TEX_FORMAT_RGB32_TYPELESS ] = NativePixelAttribs(GL_RGB, GL_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGB32_FLOAT ] = NativePixelAttribs(GL_RGB, GL_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGB32_UINT ] = NativePixelAttribs(GL_RGB_INTEGER, GL_UNSIGNED_INT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGB32_SINT ] = NativePixelAttribs(GL_RGB_INTEGER, GL_INT);
+
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA16_TYPELESS ] = NativePixelAttribs(GL_RGBA, GL_HALF_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA16_FLOAT ] = NativePixelAttribs(GL_RGBA, GL_HALF_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA16_UNORM ] = NativePixelAttribs(GL_RGBA, GL_UNSIGNED_SHORT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA16_UINT ] = NativePixelAttribs(GL_RGBA_INTEGER, GL_UNSIGNED_SHORT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA16_SNORM ] = NativePixelAttribs(GL_RGBA, GL_SHORT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA16_SINT ] = NativePixelAttribs(GL_RGBA_INTEGER, GL_SHORT);
+
+ FmtToGLPixelFmt[ TEX_FORMAT_RG32_TYPELESS ] = NativePixelAttribs(GL_RG, GL_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RG32_FLOAT ] = NativePixelAttribs(GL_RG, GL_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RG32_UINT ] = NativePixelAttribs(GL_RG_INTEGER, GL_UNSIGNED_INT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RG32_SINT ] = NativePixelAttribs(GL_RG_INTEGER, GL_INT);
+
+ FmtToGLPixelFmt[ TEX_FORMAT_R32G8X24_TYPELESS ] = NativePixelAttribs(GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
+ FmtToGLPixelFmt[ TEX_FORMAT_D32_FLOAT_S8X24_UINT ] = NativePixelAttribs(GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
+ FmtToGLPixelFmt[ TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS ]=NativePixelAttribs(GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
+ FmtToGLPixelFmt[ TEX_FORMAT_X32_TYPELESS_G8X24_UINT ]= NativePixelAttribs(GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
+
+ // Components are normally packed with the first component in the most significant
+ // bits of the bitfield, and successive component occupying progressively less
+ // significant locations.Types whose token names end with _REV reverse the component
+ // packing order from least to most significant locations.
+ FmtToGLPixelFmt[ TEX_FORMAT_RGB10A2_TYPELESS ] = NativePixelAttribs(GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGB10A2_UNORM ] = NativePixelAttribs(GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGB10A2_UINT ] = NativePixelAttribs(GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV);
+ FmtToGLPixelFmt[ TEX_FORMAT_R11G11B10_FLOAT ] = NativePixelAttribs(GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV);
+
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA8_TYPELESS ] = NativePixelAttribs(GL_RGBA, GL_UNSIGNED_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA8_UNORM ] = NativePixelAttribs(GL_RGBA, GL_UNSIGNED_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA8_UNORM_SRGB ] = NativePixelAttribs(GL_RGBA, GL_UNSIGNED_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA8_UINT ] = NativePixelAttribs(GL_RGBA_INTEGER, GL_UNSIGNED_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA8_SNORM ] = NativePixelAttribs(GL_RGBA, GL_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_RGBA8_SINT ] = NativePixelAttribs(GL_RGBA_INTEGER, GL_BYTE);
+
+ FmtToGLPixelFmt[ TEX_FORMAT_RG16_TYPELESS ] = NativePixelAttribs(GL_RG, GL_HALF_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RG16_FLOAT ] = NativePixelAttribs(GL_RG, GL_HALF_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RG16_UNORM ] = NativePixelAttribs(GL_RG, GL_UNSIGNED_SHORT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RG16_UINT ] = NativePixelAttribs(GL_RG_INTEGER, GL_UNSIGNED_SHORT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RG16_SNORM ] = NativePixelAttribs(GL_RG, GL_SHORT);
+ FmtToGLPixelFmt[ TEX_FORMAT_RG16_SINT ] = NativePixelAttribs(GL_RG_INTEGER, GL_SHORT);
+
+ FmtToGLPixelFmt[ TEX_FORMAT_R32_TYPELESS ] = NativePixelAttribs(GL_RED, GL_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_D32_FLOAT ] = NativePixelAttribs(GL_DEPTH_COMPONENT, GL_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_R32_FLOAT ] = NativePixelAttribs(GL_RED, GL_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_R32_UINT ] = NativePixelAttribs(GL_RED_INTEGER, GL_UNSIGNED_INT);
+ FmtToGLPixelFmt[ TEX_FORMAT_R32_SINT ] = NativePixelAttribs(GL_RED_INTEGER, GL_INT);
+
+ FmtToGLPixelFmt[ TEX_FORMAT_R24G8_TYPELESS ] = NativePixelAttribs(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
+ FmtToGLPixelFmt[ TEX_FORMAT_D24_UNORM_S8_UINT ] = NativePixelAttribs(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
+ FmtToGLPixelFmt[ TEX_FORMAT_R24_UNORM_X8_TYPELESS ] = NativePixelAttribs(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
+ FmtToGLPixelFmt[ TEX_FORMAT_X24_TYPELESS_G8_UINT ] = NativePixelAttribs(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
+
+ FmtToGLPixelFmt[ TEX_FORMAT_RG8_TYPELESS ] = NativePixelAttribs(GL_RG, GL_UNSIGNED_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_RG8_UNORM ] = NativePixelAttribs(GL_RG, GL_UNSIGNED_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_RG8_UINT ] = NativePixelAttribs(GL_RG_INTEGER, GL_UNSIGNED_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_RG8_SNORM ] = NativePixelAttribs(GL_RG, GL_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_RG8_SINT ] = NativePixelAttribs(GL_RG_INTEGER, GL_BYTE);
+
+ FmtToGLPixelFmt[ TEX_FORMAT_R16_TYPELESS ] = NativePixelAttribs(GL_RED, GL_HALF_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_R16_FLOAT ] = NativePixelAttribs(GL_RED, GL_HALF_FLOAT);
+ FmtToGLPixelFmt[ TEX_FORMAT_D16_UNORM ] = NativePixelAttribs(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
+ FmtToGLPixelFmt[ TEX_FORMAT_R16_UNORM ] = NativePixelAttribs(GL_RED, GL_UNSIGNED_SHORT);
+ FmtToGLPixelFmt[ TEX_FORMAT_R16_UINT ] = NativePixelAttribs(GL_RED_INTEGER, GL_UNSIGNED_SHORT);
+ FmtToGLPixelFmt[ TEX_FORMAT_R16_SNORM ] = NativePixelAttribs(GL_RED, GL_SHORT);
+ FmtToGLPixelFmt[ TEX_FORMAT_R16_SINT ] = NativePixelAttribs(GL_RED_INTEGER, GL_SHORT);
+
+ FmtToGLPixelFmt[ TEX_FORMAT_R8_TYPELESS ] = NativePixelAttribs(GL_RED, GL_UNSIGNED_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_R8_UNORM ] = NativePixelAttribs(GL_RED, GL_UNSIGNED_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_R8_UINT ] = NativePixelAttribs(GL_RED_INTEGER, GL_UNSIGNED_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_R8_SNORM ] = NativePixelAttribs(GL_RED, GL_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_R8_SINT ] = NativePixelAttribs(GL_RED_INTEGER, GL_BYTE);
+ FmtToGLPixelFmt[ TEX_FORMAT_A8_UNORM ] = NativePixelAttribs();
+
+ FmtToGLPixelFmt[ TEX_FORMAT_R1_UNORM ] = NativePixelAttribs();
+
+ FmtToGLPixelFmt[ TEX_FORMAT_RGB9E5_SHAREDEXP ] = NativePixelAttribs(GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV);
+ FmtToGLPixelFmt[ TEX_FORMAT_RG8_B8G8_UNORM ] = NativePixelAttribs();
+ FmtToGLPixelFmt[ TEX_FORMAT_G8R8_G8B8_UNORM ] = NativePixelAttribs();
+
+ // http://www.g-truc.net/post-0335.html
+ // http://renderingpipeline.com/2012/07/texture-compression/
+ FmtToGLPixelFmt[ TEX_FORMAT_BC1_TYPELESS ] = NativePixelAttribs(GL_RGB, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC1_UNORM ] = NativePixelAttribs(GL_RGB, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC1_UNORM_SRGB ] = NativePixelAttribs(GL_RGB, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC2_TYPELESS ] = NativePixelAttribs(GL_RGBA, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC2_UNORM ] = NativePixelAttribs(GL_RGBA, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC2_UNORM_SRGB ] = NativePixelAttribs(GL_RGBA, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC3_TYPELESS ] = NativePixelAttribs(GL_RGBA, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC3_UNORM ] = NativePixelAttribs(GL_RGBA, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC3_UNORM_SRGB ] = NativePixelAttribs(GL_RGBA, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC4_TYPELESS ] = NativePixelAttribs(GL_RED, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC4_UNORM ] = NativePixelAttribs(GL_RED, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC4_SNORM ] = NativePixelAttribs(GL_RED, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC5_TYPELESS ] = NativePixelAttribs(GL_RG, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC5_UNORM ] = NativePixelAttribs(GL_RG, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC5_SNORM ] = NativePixelAttribs(GL_RG, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_B5G6R5_UNORM ] = NativePixelAttribs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV);
+ FmtToGLPixelFmt[ TEX_FORMAT_B5G5R5A1_UNORM ] = NativePixelAttribs(GL_RGB, GL_UNSIGNED_SHORT_1_5_5_5_REV);
+ FmtToGLPixelFmt[ TEX_FORMAT_BGRA8_UNORM ] = NativePixelAttribs();
+ FmtToGLPixelFmt[ TEX_FORMAT_BGRX8_UNORM ] = NativePixelAttribs();
+ FmtToGLPixelFmt[ TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM ] = NativePixelAttribs();
+ FmtToGLPixelFmt[ TEX_FORMAT_BGRA8_TYPELESS ] = NativePixelAttribs();
+ FmtToGLPixelFmt[ TEX_FORMAT_BGRA8_UNORM_SRGB ] = NativePixelAttribs();
+ FmtToGLPixelFmt[ TEX_FORMAT_BGRX8_TYPELESS ] = NativePixelAttribs();
+ FmtToGLPixelFmt[ TEX_FORMAT_BGRX8_UNORM_SRGB ] = NativePixelAttribs();
+ FmtToGLPixelFmt[ TEX_FORMAT_BC6H_TYPELESS ] = NativePixelAttribs(GL_RGB, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC6H_UF16 ] = NativePixelAttribs(GL_RGB, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC6H_SF16 ] = NativePixelAttribs(GL_RGB, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC7_TYPELESS ] = NativePixelAttribs(GL_RGBA, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC7_UNORM ] = NativePixelAttribs(GL_RGBA, 0, True);
+ FmtToGLPixelFmt[ TEX_FORMAT_BC7_UNORM_SRGB ] = NativePixelAttribs(GL_RGBA, 0, True);
+
+ bAttribsMapIntialized = true;
+ }
+
+ if( TexFormat > TEX_FORMAT_UNKNOWN && TexFormat < TEX_FORMAT_NUM_FORMATS )
+ {
+ return FmtToGLPixelFmt[TexFormat];
+ }
+ else
+ {
+ UNEXPECTED( "Texture format (", TexFormat, ") is out of allowed range [1, ", TEX_FORMAT_NUM_FORMATS-1, "]" );
+ return FmtToGLPixelFmt[0];
+ }
+}
+
+GLenum AccessFlags2GLAccess( Uint32 UAVAccessFlags )
+{
+ static GLenum AccessFlags2GLAccessMap[UAV_ACCESS_FLAG_READ_WRITE + 1] = {};
+ static bool bIsInit = false;
+ if( !bIsInit )
+ {
+ AccessFlags2GLAccessMap[UAV_ACCESS_FLAG_READ] = GL_READ_ONLY;
+ AccessFlags2GLAccessMap[UAV_ACCESS_FLAG_WRITE] = GL_WRITE_ONLY;
+ AccessFlags2GLAccessMap[UAV_ACCESS_FLAG_READ_WRITE] = GL_READ_WRITE;
+ bIsInit = true;
+ }
+
+ auto GLAccess = AccessFlags2GLAccessMap[UAVAccessFlags & UAV_ACCESS_FLAG_READ_WRITE];
+ return GLAccess;
+}
+
+
+GLenum TypeToGLTexFormat( VALUE_TYPE ValType, Uint32 NumComponents, Bool bIsNormalized )
+{
+ switch( ValType )
+ {
+ case VT_FLOAT16:
+ {
+ VERIFY( !bIsNormalized, "Floating point formats cannot be normalized" );
+ switch( NumComponents )
+ {
+ case 1: return GL_R16F;
+ case 2: return GL_RG16F;
+ case 4: return GL_RGBA16F;
+ default: UNEXPECTED( "Unusupported number of components" ); return 0;
+ }
+ }
+
+ case VT_FLOAT32:
+ {
+ VERIFY( !bIsNormalized, "Floating point formats cannot be normalized" );
+ switch( NumComponents )
+ {
+ case 1: return GL_R32F;
+ case 2: return GL_RG32F;
+ case 3: return GL_RGB32F;
+ case 4: return GL_RGBA32F;
+ default: UNEXPECTED( "Unusupported number of components" ); return 0;
+ }
+ }
+
+ case VT_INT32:
+ {
+ VERIFY( !bIsNormalized , "32-bit UNORM formats are not supported. Use R32_FLOAT instead" );
+ switch( NumComponents )
+ {
+ case 1: return GL_R32I;
+ case 2: return GL_RG32I;
+ case 3: return GL_RGB32I;
+ case 4: return GL_RGBA32I;
+ default: UNEXPECTED( "Unusupported number of components" ); return 0;
+ }
+ }
+
+ case VT_UINT32:
+ {
+ VERIFY( !bIsNormalized, "32-bit UNORM formats are not supported. Use R32_FLOAT instead" );
+ switch( NumComponents )
+ {
+ case 1: return GL_R32UI;
+ case 2: return GL_RG32UI;
+ case 3: return GL_RGB32UI;
+ case 4: return GL_RGBA32UI;
+ default: UNEXPECTED( "Unusupported number of components" ); return 0;
+ }
+ }
+
+ case VT_INT16:
+ {
+ if( bIsNormalized )
+ {
+ switch( NumComponents )
+ {
+ case 1: return GL_R16_SNORM;
+ case 2: return GL_RG16_SNORM;
+ case 4: return GL_RGBA16_SNORM;
+ default: UNEXPECTED( "Unusupported number of components" ); return 0;
+ }
+ }
+ else
+ {
+ switch( NumComponents )
+ {
+ case 1: return GL_R16I;
+ case 2: return GL_RG16I;
+ case 4: return GL_RGBA16I;
+ default: UNEXPECTED( "Unusupported number of components" ); return 0;
+ }
+ }
+ }
+
+ case VT_UINT16:
+ {
+ if( bIsNormalized )
+ {
+ switch( NumComponents )
+ {
+ case 1: return GL_R16;
+ case 2: return GL_RG16;
+ case 4: return GL_RGBA16;
+ default: UNEXPECTED( "Unusupported number of components" ); return 0;
+ }
+ }
+ else
+ {
+ switch( NumComponents )
+ {
+ case 1: return GL_R16UI;
+ case 2: return GL_RG16UI;
+ case 4: return GL_RGBA16UI;
+ default: UNEXPECTED( "Unusupported number of components" ); return 0;
+ }
+ }
+ }
+
+ case VT_INT8:
+ {
+ if( bIsNormalized )
+ {
+ switch( NumComponents )
+ {
+ case 1: return GL_R8_SNORM;
+ case 2: return GL_RG8_SNORM;
+ case 4: return GL_RGBA8_SNORM;
+ default: UNEXPECTED( "Unusupported number of components" ); return 0;
+ }
+ }
+ else
+ {
+ switch( NumComponents )
+ {
+ case 1: return GL_R8I;
+ case 2: return GL_RG8I;
+ case 4: return GL_RGBA8I;
+ default: UNEXPECTED( "Unusupported number of components" ); return 0;
+ }
+ }
+ }
+
+ case VT_UINT8:
+ {
+ if( bIsNormalized )
+ {
+ switch( NumComponents )
+ {
+ case 1: return GL_R8;
+ case 2: return GL_RG8;
+ case 4: return GL_RGBA8;
+ default: UNEXPECTED( "Unusupported number of components" ); return 0;
+ }
+ }
+ else
+ {
+ switch( NumComponents )
+ {
+ case 1: return GL_R8UI;
+ case 2: return GL_RG8UI;
+ case 4: return GL_RGBA8UI;
+ default: UNEXPECTED( "Unusupported number of components" ); return 0;
+ }
+ }
+ }
+
+ default: UNEXPECTED( "Unusupported format" ); return 0;
+ }
+}
+
+GLenum StencilOp2GlStencilOp( STENCIL_OP StencilOp )
+{
+ static bool bIsInit = false;
+ static GLenum GLStencilOps[STENCIL_OP_NUM_OPS] = {};
+ if( !bIsInit )
+ {
+ GLStencilOps[STENCIL_OP_KEEP] = GL_KEEP;
+ GLStencilOps[STENCIL_OP_ZERO] = GL_ZERO;
+ GLStencilOps[STENCIL_OP_REPLACE] = GL_REPLACE;
+ GLStencilOps[STENCIL_OP_INCR_SAT] = GL_INCR;
+ GLStencilOps[STENCIL_OP_DECR_SAT] = GL_DECR;
+ GLStencilOps[STENCIL_OP_INVERT] = GL_INVERT;
+ GLStencilOps[STENCIL_OP_INCR_WRAP]= GL_INCR_WRAP;
+ GLStencilOps[STENCIL_OP_DECR_WRAP]= GL_DECR_WRAP;
+ bIsInit = true;
+ }
+
+ if( StencilOp > STENCIL_OP_UNDEFINED && StencilOp < STENCIL_OP_NUM_OPS )
+ {
+ auto GlStencilOp = GLStencilOps[StencilOp];
+ VERIFY( GlStencilOp != 0 || GlStencilOp == 0 && StencilOp == STENCIL_OP_ZERO, "Unexpected stencil op" );
+ return GlStencilOp;
+ }
+ else
+ {
+ UNEXPECTED( "Stencil operation (", StencilOp, ") is out of allowed range [1, ", STENCIL_OP_NUM_OPS-1, "]" );
+ return 0;
+ }
+}
+
+
+GLenum BlendFactor2GLBlend( BLEND_FACTOR bf )
+{
+ static bool bIsInit = false;
+ static GLenum GLBlend[BLEND_FACTOR_NUM_FACTORS] = {};
+ if( !bIsInit )
+ {
+ GLBlend[ BLEND_FACTOR_ZERO ] = GL_ZERO;
+ GLBlend[ BLEND_FACTOR_ONE ] = GL_ONE;
+ GLBlend[ BLEND_FACTOR_SRC_COLOR ] = GL_SRC_COLOR;
+ GLBlend[ BLEND_FACTOR_INV_SRC_COLOR ] = GL_ONE_MINUS_SRC_COLOR;
+ GLBlend[ BLEND_FACTOR_SRC_ALPHA ] = GL_SRC_ALPHA;
+ GLBlend[ BLEND_FACTOR_INV_SRC_ALPHA ] = GL_ONE_MINUS_SRC_ALPHA;
+ GLBlend[ BLEND_FACTOR_DEST_ALPHA ] = GL_DST_ALPHA;
+ GLBlend[ BLEND_FACTOR_INV_DEST_ALPHA ] = GL_ONE_MINUS_DST_ALPHA;
+ GLBlend[ BLEND_FACTOR_DEST_COLOR ] = GL_DST_COLOR;
+ GLBlend[ BLEND_FACTOR_INV_DEST_COLOR ] = GL_ONE_MINUS_DST_COLOR;
+ GLBlend[ BLEND_FACTOR_SRC_ALPHA_SAT ] = GL_SRC_ALPHA_SATURATE;
+ GLBlend[ BLEND_FACTOR_BLEND_FACTOR ] = GL_CONSTANT_COLOR;
+ GLBlend[ BLEND_FACTOR_INV_BLEND_FACTOR ] = GL_ONE_MINUS_CONSTANT_COLOR;
+ GLBlend[ BLEND_FACTOR_SRC1_COLOR ] = GL_SRC1_COLOR;
+ GLBlend[ BLEND_FACTOR_INV_SRC1_COLOR ] = GL_ONE_MINUS_SRC1_COLOR;
+ GLBlend[ BLEND_FACTOR_SRC1_ALPHA ] = GL_SRC1_ALPHA;
+ GLBlend[ BLEND_FACTOR_INV_SRC1_ALPHA ] = GL_ONE_MINUS_SRC1_ALPHA;
+
+ bIsInit = true;
+ }
+ if( bf > BLEND_FACTOR_UNDEFINED && bf < BLEND_FACTOR_NUM_FACTORS )
+ {
+ auto glbf = GLBlend[bf];
+ VERIFY( glbf != 0 || glbf == 0 && bf == BLEND_FACTOR_ZERO, "Incorrect blend factor" );
+ return glbf;
+ }
+ else
+ {
+ UNEXPECTED( "Incorrect blend factor (", bf, ")" );
+ return 0;
+ }
+}
+
+GLenum BlendOperation2GLBlendOp( BLEND_OPERATION BlendOp )
+{
+ static bool bIsInit = false;
+ static GLenum GLBlendOp[BLEND_OPERATION_NUM_OPERATIONS] = {};
+ if( !bIsInit )
+ {
+ GLBlendOp[ BLEND_OPERATION_ADD ] = GL_FUNC_ADD;
+ GLBlendOp[ BLEND_OPERATION_SUBTRACT ] = GL_FUNC_SUBTRACT;
+ GLBlendOp[ BLEND_OPERATION_REV_SUBTRACT ] = GL_FUNC_REVERSE_SUBTRACT;
+ GLBlendOp[ BLEND_OPERATION_MIN ] = GL_MIN;
+ GLBlendOp[ BLEND_OPERATION_MAX ] = GL_MAX;
+
+ bIsInit = true;
+ }
+
+ if( BlendOp > BLEND_OPERATION_UNDEFINED && BlendOp < BLEND_OPERATION_NUM_OPERATIONS )
+ {
+ auto glbop = GLBlendOp[BlendOp];
+ VERIFY( glbop != 0, "Incorrect blend operation" );
+ return glbop;
+ }
+ else
+ {
+ UNEXPECTED( "Incorrect blend operation (", BlendOp, ")" );
+ return 0;
+ }
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/GraphicsEngineOpenGL.def b/Graphics/GraphicsEngineOpenGL/src/GraphicsEngineOpenGL.def
new file mode 100644
index 00000000..3a128b26
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/GraphicsEngineOpenGL.def
@@ -0,0 +1,2 @@
+EXPORTS
+ CreateDeviceAndSwapChainGL \ No newline at end of file
diff --git a/Graphics/GraphicsEngineOpenGL/src/HLSL2GLSLConverter.cpp b/Graphics/GraphicsEngineOpenGL/src/HLSL2GLSLConverter.cpp
new file mode 100644
index 00000000..252383ba
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/HLSL2GLSLConverter.cpp
@@ -0,0 +1,3261 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+// Converter limitation:
+// * Using Texture* keywords in macros is not supported. The following lines will not work:
+// - #define TEXTURE2D Texture2D
+// TEXTURE2D MacroTex2D;
+//
+//
+// List of supported HLSL Objects and methods:
+//
+// * Texture1D:
+// - void GetDimensions (out {int, uint, float} Width);
+// - void GetDimensions (in uint MipLevel, out {int, uint, float} Width, out {int, uint, float} NumberOfLevels);
+// - ret Sample( sampler_state S, float Location [, int Offset] );
+// - ret SampleBias( sampler_state S, float Location, float Bias [, int Offset] );
+// - ret SampleLevel( sampler_state S, float Location, float LOD [, int Offset] )
+// - ret SampleGrad( sampler_state S, float Location, float DDX, float DDY [, int Offset] );
+// - float SampleCmp( SamplerComparisonState S, float Location, float CompareValue, [int Offset] );
+// - float SampleCmpLevelZero( SamplerComparisonState S, float Location, float CompareValue, [int Offset] );
+// - ret Load( int Location, [int Offset ] );
+//
+//
+// * Texture1DArray:
+// - void GetDimensions( out {int, uint, float} Width, out {int, uint, float} Elements );
+// - void GetDimensions( in uint MipLevel, out {int, uint, float} Width, out {int, uint, float} Elements, out {int, uint, float} NumberOfLevels );
+// - ret Sample( sampler_state S, float2 Location [, int Offset] );
+// - ret SampleBias( sampler_state S, float2 Location, float Bias [, int Offset] );
+// - ret SampleLevel( sampler_state S, float2 Location, float LOD [, int Offset] )
+// - ret SampleGrad( sampler_state S, float2 Location, float DDX, float DDY [, int Offset] );
+// - float SampleCmp( SamplerComparisonState S, float2 Location, float CompareValue, [int Offset] );
+// - float SampleCmpLevelZero( SamplerComparisonState S, float2 Location, float CompareValue, [int Offset] );
+// - ret Load( int2 Location, [int Offset ] );
+// Remarks:
+// - Array index goes in Location.y
+
+//
+// * Texture2D:
+// - void GetDimensions( out {int, uint, float} Width, out {int, uint, float} Height );
+// - void GetDimensions( in uint MipLevel, out {int, uint, float} Width, out {int, uint, float} Height, out {int, uint, float} NumberOfLevels );
+// - ret Sample( sampler_state S, float2 Location [, int2 Offset] );
+// - ret SampleBias( sampler_state S, float2 Location, float Bias [, int2 Offset] );
+// - ret SampleLevel( sampler_state S, float2 Location, float LOD [, int2 Offset] )
+// - ret SampleGrad( sampler_state S, float2 Location, float2 DDX, float2 DDY [, int2 Offset] );
+// - float SampleCmp( SamplerComparisonState S, float2 Location, float CompareValue, [int2 Offset] );
+// - float SampleCmpLevelZero( SamplerComparisonState S, float2 Location, float CompareValue [, int2 Offset] );
+// - ret Load( int2 Location, [int2 Offset ] );
+// - ret Gather( sampler_state S, float2 Location [, int2 Offset] );
+// - float4 GatherCmp( SamplerComparisonState S, float2 Location, float CompareValue [, int2 Offset] );
+//
+// * Texture2DArray:
+// - void GetDimensions( out {int, uint, float} Width, out {int, uint, float} Height, out {int, uint, float} Elements );
+// - void GetDimensions( in uint MipLevel, out {int, uint, float} Width, out {int, uint, float} Height, out {int, uint, float} Elements, out {int, uint, float} NumberOfLevels );
+// - ret Sample( sampler_state S, float3 Location [, int2 Offset] );
+// - ret SampleBias( sampler_state S, float3 Location, float Bias [, int2 Offset] );
+// - ret SampleLevel( sampler_state S, float3 Location, float LOD [, int2 Offset] )
+// - ret SampleGrad( sampler_state S, float3 Location, float2 DDX, float2 DDY [, int2 Offset] );
+// - float SampleCmp( SamplerComparisonState S, float2 Location, float CompareValue [, int2 Offset] );
+// - ret Load( int Location3 [, int2 Offset ] );
+// - ret Gather( sampler_state S, float3 Location [, int2 Offset] );
+// - float4 GatherCmp( SamplerComparisonState S, float3 Location, float CompareValue [, int2 Offset] );
+// Remarks:
+// - Array index goes in Location.z
+// - SampleCmpLevelZero() is not supported as there is no corresponding OpenGL instruction. The
+// instruction will always return 0.
+//
+// * Texture3D:
+// - void GetDimensions( out {int, uint, float} Width, out {int, uint, float} Height, out {int, uint, float} Depth );
+// - void GetDimensions( in uint MipLevel, out {int, uint, float} Width, out {int, uint, float} Height, out {int, uint, float} Depth, out {int, uint, float} NumberOfLevels );
+// - ret Sample( sampler_state S, float3 Location [, int3 Offset] );
+// - ret SampleBias( sampler_state S, float3 Location, float Bias [, int3 Offset] );
+// - ret SampleLevel( sampler_state S, float3 Location, float LOD [, int3 Offset] )
+// - ret SampleGrad( sampler_state S, float3 Location, float3 DDX, float3 DDY [, int3 Offset] );
+// - ret Load( int3 Location [, int3 Offset ] );
+//
+// * TextureCube:
+// - void GetDimensions( out {int, uint, float} Width, out {int, uint, float} Height );
+// - void GetDimensions( in uint MipLevel, out {int, uint, float} Width, out {int, uint, float} Height, out {int, uint, float} NumberOfLevels );
+// - ret Sample( sampler_state S, float3 Location );
+// - ret SampleBias( sampler_state S, float3 Location, float Bias );
+// - ret SampleLevel( sampler_state S, float3 Location, float LOD ) - NO offset version
+// - ret SampleGrad( sampler_state S, float3 Location, float3 DDX, float3 DDY );
+// - float SampleCmp( SamplerComparisonState S, float3 Location, float CompareValue );
+// - ret Gather( sampler_state S, float3 Location );
+// - float4 GatherCmp( SamplerComparisonState S, float3 Location, float CompareValue );
+// Remarks:
+// - SampleCmpLevelZero() is not supported as there is no corresponding OpenGL instruction. The
+// instruction will always return 0.
+
+// * TextureCubeArray:
+// - void GetDimensions( out {int, uint, float} Width, out {int, uint, float} Height, out {int, uint, float} Elements );
+// - void GetDimensions( in uint MipLevel, out {int, uint, float} Width, out {int, uint, float} Height, out {int, uint, float} Elements, out {int, uint, float} NumberOfLevels );
+// - ret Sample( sampler_state S, float4 Location );
+// - ret SampleBias( sampler_state S, float4 Location, float Bias );
+// - ret SampleLevel( sampler_state S, float4 Location, float LOD ) - NO offset version
+// - ret SampleGrad( sampler_state S, float4 Location, float3 DDX, float3 DDY );
+// - float SampleCmp( SamplerComparisonState S, float4 Location, float CompareValue );
+// - ret Gather( sampler_state S, float4 Location );
+// - float4 GatherCmp( SamplerComparisonState S, float4 Location, float CompareValue );
+// Remarks:
+// - SampleCmpLevelZero() is not supported as there is no corresponding OpenGL instruction. The
+// instruction will always return 0.
+// - Array index goes in Location.w
+//
+// * Texture2DMS:
+// - void GetDimensions(out {int, uint, float} Width, out {int, uint, float} Height, out {int, uint, float} NumberOfSamples);
+// - ret Load( int2 Location, int Sample, [int2 Offset ] );
+//
+// * Texture2DMSArray:
+// - void GetDimensions( out {int, uint, float} Width, out {int, uint, float} Height, out {int, uint, float} Elements, out {int, uint, float} NumberOfSamples );
+// - ret Load( int3 Location, int Sample, [int2 Offset ] );
+//
+//
+// * RWTexture1D:
+// - void GetDimensions(out {int, uint, float} Width);
+//
+// * RWTexture1DArray:
+// - void GetDimensions(out {int, uint, float} Width, out {int, uint, float} Elements);
+//
+// * RWTexture2D:
+// - void GetDimensions(out {int, uint, float} Width, out {int, uint, float} Height);
+//
+// * RWTexture2DArray:
+// - void GetDimensions(out {int, uint, float} Width, out {int, uint, float} Height, out {int, uint, float} Elements);
+//
+// * RWTexture3D:
+// - void GetDimensions(out {int, uint, float} Width, out {int, uint, float} Height, out {int, uint, float} Depth);
+//
+
+// \remarks
+// All GetDimensions() functions return valid value in NumberOfLevels only on Desktop GL 4.3+
+// For multisampled textures, GetDimensions() always returns 0 in NumberOfSamples.
+
+
+// Support for HLSL intrinsics:
+
+// [V] abs( {int, int2, int3, int4, float, float2, float3, float4} )
+// [V] acos( {float, float2, float3, float4} )
+// (-) acos( {matrix types} )
+// [V] all( {bool2, bool3, bool4})
+// (-) all( {bool, int, int2, int3, int4, float, float2, float3, float4, matrix types} )
+// [V] any( {bool2, bool3, bool4})
+// (-) any( {bool, int, int2, int3, int4, float, float2, float3, float4, matrix types} )
+// [V] asdouble( {uint} )
+// [V] asfloat( {int, int2, int3, int4, uint, uint2, uint3, uint4, float, float2, float3, float4} )
+// (-) asfloat( {matrix types} )
+// [V] asint( {int, int2, int3, int4, uint, uint2, uint3, uint4, float, float2, float3, float4} )
+// (-) asint( {matrix types} )
+// [V] asuint( {int, int2, int3, int4, uint, uint2, uint3, uint4, float, float2, float3, float4} )
+// (-) asuint( {matrix types} )
+// [V] asin( {float, float2, float3, float4} )
+// (-) asin( {matrix types} )
+// [V] atan( {float, float2, float3, float4} )
+// (-) atan( {matrix types} )
+// [V] atan2( {float, float2, float3, float4} )
+// (-) atan2( {matrix types} )
+// [V] ceil( {float, float2, float3, float4} )
+// (-) ceil( {matrix types} )
+// [V] clamp( {int, int2, int3, int4, uint, uint2, uint3, uint4, float, float2, float3, float4} )
+// (-) clamp( {matrix types} )
+// [V] cos( {float, float2, float3, float4} )
+// (-) cos( {matrix types} )
+// [V] cosh( {float, float2, float3, float4} )
+// (-) cosh( {matrix types} )
+// [V] countbits( {int, int2, int3, int4, uint, uint2, uint3, uint4} )
+// [V] cross(float3)
+// [V] ddx
+// [V] ddx_coarse - defined as ddx
+// [V] ddx_fine - defined as ddx
+// [V] ddy
+// [V] ddy_coarse - defined as ddy
+// [V] ddy_fine - defined as ddy
+// [V] degrees( {float, float2, float3, float4} )
+// (-) degrees( {matrix types} )
+// [V] determinant
+// [V] distance( {float, float2, float3, float4} )
+// [V] dot( {float, float2, float3, float4} )
+// (-) dot( {int, int2, int3, int4} )
+// [V] dst - defined as distance
+// [V] exp( {float, float2, float3, float4} )
+// (-) exp( {matrix types} )
+// [V] exp2( {float, float2, float3, float4} )
+// (-) exp2( {matrix types} )
+// [V] f16tof32( {int, int2, int3, int4, uint, uint2, uint3, uint4} )
+// [V] f32tof16( {float, float2, float3, float4} ) -> {uint, uint2, uint3, uint4}
+// [V] faceforward( {float, float2, float3, float4} )
+// [V] firstbithigh( {int, int2, int3, int4, uint, uint2, uint3, uint4} )
+// [V] firstbitlow( {int, int2, int3, int4, uint, uint2, uint3, uint4} )
+// [V] floor( {float, float2, float3, float4} )
+// (-) floor( {matrix types} )
+// [V] fma( {double, double2, double3, double4} )
+// [V] fmod( {float, float2, float3, float4} )
+// (-) fmod( {matrix types} )
+// [V] frac( {float, float2, float3, float4} )
+// (-) frac( {matrix types} )
+// [V] frexp( {float, float2, float3, float4}, {int, int2, int3, int4} )
+// [V] fwidth( {float, float2, float3, float4} )
+// (-) fwidth( {matrix types} )
+// [V] isfinite( {float, float2, float3, float4} ) - implemented as (!isinf(x) && !isnan(x))
+// [V] isinf( {float, float2, float3, float4} )
+// (-) isinf( {matrix types} )
+// [V] isnan( {float, float2, float3, float4} )
+// (-) isnan( {matrix types} )
+// [V] ldexp( {float, float2, float3, float4}, {int, int2, int3, int4} )
+// [V] length( {float, float2, float3, float4} )
+// [V] lerp( {float, float2, float3, float4} )
+// (-) lerp( {matrix types} )
+// [V] log( {float, float2, float3, float4} )
+// (-) log( {matrix types} )
+// [V] log2( {float, float2, float3, float4} )
+// (-) log2( {matrix types} )
+// [V] log10( {float, float2, float3, float4} )
+// (-) log10( {matrix types} )
+// [V] mad( {float, float2, float3, float4} )
+// (-) mad( {matrix types} )
+// [V] max( {int, int2, int3, int4, uint, uint2, uint3, uint4, float, float2, float3, float4} )
+// (-) max( {matrix types} )
+// [V] min( {int, int2, int3, int4, uint, uint2, uint3, uint4, float, float2, float3, float4} )
+// (-) min( {matrix types} )
+// [V] modf( {float, float2, float3, float4} )
+// (-) modf( {int, int2, int3, int4, matrix types} )
+// [V] mul - defined as a*b
+// [V] noise( {float, float2, float3, float4} )
+// [V] normalize( {float, float2, float3, float4} )
+// [V] pow( {float, float2, float3, float4} )
+// (-) pow( {matrix types} )
+// [V] radians( {float, float2, float3, float4} )
+// (-) radians( {matrix types} )
+// [V] rcp( {float, float2, float3, float4} ) - defined as 1.0/(x)
+// [V] reflect( {float, float2, float3, float4} )
+// [V] refract( {float, float2, float3, float4} )
+// [V] reversebits( {int, int2, int3, int4, uint, uint2, uint3, uint4} )
+// [V] round( {float, float2, float3, float4} )
+// (-) round( {matrix types} )
+// [V] rsqrt( {float, float2, float3, float4} )
+// (-) rsqrt( {matrix types} )
+// [V] saturate( {float, float2, float3, float4} )
+// [V] sign( {float, float2, float3, float4, int, int2, int3, int4} )
+// (-) sign( {matrix types} )
+// [V] sin( {float, float2, float3, float4} )
+// (-) sin( {matrix types} )
+// [V] sinh( {float, float2, float3, float4} )
+// (-) sinh( {matrix types} )
+// [V] sincos( {float, float2, float3, float4} )
+// [V] smoothstep( {float, float2, float3, float4} )
+// (-) smoothstep( {matrix types} )
+// [V] sqrt( {float, float2, float3, float4} )
+// (-) sqrt( {matrix types} )
+// [V] step( {float, float2, float3, float4} )
+// (-) step( {matrix types} )
+// [V] tan( {float, float2, float3, float4} )
+// (-) tan( {matrix types} )
+// [V] tanh( {float, float2, float3, float4} )
+// (-) tanh( {matrix types} )
+// [V] transpose
+// [V] trunc( {float, float2, float3, float4} )
+// (-) trunc( {matrix types} )
+
+// [V] AllMemoryBarrier - calls all memory barrier functions in gl
+// [V] AllMemoryBarrierWithGroupSync
+// [V] DeviceMemoryBarrier - calls image, atomic counter & buffer memory barriers
+// [V] DeviceMemoryBarrierWithGroupSync
+// [V] GroupMemoryBarrier - calls group memory & shared memory barriers
+// [V] GroupMemoryBarrierWithGroupSync
+
+// [V] InterlockedAdd( {int, uint} )
+// [V] InterlockedAnd( {int, uint} )
+// [V] InterlockedCompareExchange( {int, uint} )
+// [V] InterlockedCompareStore( {int, uint} )
+// [V] InterlockedExchange( {int, uint} )
+// [V] InterlockedMax( {int, uint} )
+// [V] InterlockedMin( {int, uint} )
+// [V] InterlockedOr( {int, uint} )
+// [V] InterlockedXor( {int, uint} )
+
+// [ ] Process2DQuadTessFactorsAvg
+// [ ] Process2DQuadTessFactorsMax
+// [ ] Process2DQuadTessFactorsMin
+// [ ] ProcessIsolineTessFactors
+// [ ] ProcessQuadTessFactorsAvg
+// [ ] ProcessQuadTessFactorsMax
+// [ ] ProcessQuadTessFactorsMin
+// [ ] ProcessTriTessFactorsAvg
+// [ ] ProcessTriTessFactorsMax
+// [ ] ProcessTriTessFactorsMin
+
+// [ ] CheckAccessFullyMapped
+
+// [ ] GetRenderTargetSampleCount
+// [ ] GetRenderTargetSamplePosition
+
+// [ ] EvaluateAttributeAtCentroid
+// [ ] EvaluateAttributeAtSample
+// [ ] EvaluateAttributeSnapped
+
+// [ ] abort
+// [ ] errorf
+// [ ] printf
+// [ ] clip
+// [ ] msad4
+// [ ] lit
+
+// [ ] D3DCOLORtoUBYTE4
+
+// Legacy not supported functions:
+// [ ] tex1D
+// [ ] tex1D
+// [ ] tex1Dbias
+// [ ] tex1Dgrad
+// [ ] tex1Dlod
+// [ ] tex1Dproj
+// [ ] tex2D
+// [ ] tex2D
+// [ ] tex2Dbias
+// [ ] tex2Dgrad
+// [ ] tex2Dlod
+// [ ] tex2Dproj
+// [ ] tex3D
+// [ ] tex3D
+// [ ] tex3Dbias
+// [ ] tex3Dgrad
+// [ ] tex3Dlod
+// [ ] tex3Dproj
+// [ ] texCUBE
+// [ ] texCUBE
+// [ ] texCUBEbias
+// [ ] texCUBEgrad
+// [ ] texCUBElod
+// [ ] texCUBEproj
+
+
+#include "pch.h"
+#include "HLSL2GLSLConverter.h"
+#include "DataBlobImpl.h"
+#include <unordered_set>
+#include <string>
+
+namespace Diligent
+{
+
+inline bool IsNewLine(Char Symbol)
+{
+ return Symbol == '\r' || Symbol == '\n';
+}
+
+inline bool IsDelimiter(Char Symbol)
+{
+ static const Char* Delimeters = " \t\r\n";
+ return strchr( Delimeters, Symbol ) != nullptr;
+}
+
+inline bool IsStatementSeparator(Char Symbol)
+{
+ static const Char* StatementSeparator = ";}";
+ return strchr( StatementSeparator, Symbol ) != nullptr;
+}
+
+
+// IteratorType may be String::iterator or String::const_iterator.
+// While iterator is convertible to const_iterator,
+// iterator& cannot be converted to const_iterator& (Microsoft compiler allows
+// such conversion, while gcc does not)
+template<typename InteratorType>
+static bool SkipComment( const String &Input, InteratorType& Pos )
+{
+ // // Comment /* Comment
+ // ^ ^
+ if( Pos == Input.end() || *Pos != '/' )
+ return false;
+
+ auto NextPos = Pos+1;
+ // // Comment /* Comment
+ // ^ ^
+ if( NextPos == Input.end() )
+ return false;
+
+ if( *NextPos == '/' )
+ {
+ // Skip // comment
+ Pos = NextPos + 1;
+ // // Comment
+ // ^
+ for( ; Pos != Input.end() && !IsNewLine(*Pos); ++Pos );
+ return true;
+ }
+ else if( *NextPos == '*' )
+ {
+ // Skip /* comment */
+ Pos = NextPos + 1;
+ // /* Comment
+ // ^
+ while( Pos != Input.end() )
+ {
+ if( *Pos == '*' )
+ {
+ // /* Comment */
+ // ^
+ ++Pos;
+ // /* Comment */
+ // ^
+ if( Pos == Input.end() )
+ break;
+ if( *Pos == '/' )
+ {
+ ++Pos;
+ // /* Comment */
+ // ^
+ break;
+ }
+ }
+ else
+ {
+ // Must handle /* **/ properly
+ ++Pos;
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+inline bool SkipDelimeters(const String &Input, String::const_iterator &SrcChar)
+{
+ for( ; SrcChar != Input.end() && IsDelimiter(*SrcChar); ++SrcChar );
+ return SrcChar == Input.end();
+}
+
+// IteratorType may be String::iterator or String::const_iterator.
+// While iterator is convertible to const_iterator,
+// iterator& cannot be converted to const_iterator& (Microsoft compiler allows
+// such conversion, while gcc does not)
+template<typename IteratorType>
+inline bool SkipDelimetersAndComments(const String &Input, IteratorType &SrcChar)
+{
+ bool DelimiterFound = false;
+ bool CommentFound = false;
+ do
+ {
+ DelimiterFound = false;
+ for( ; SrcChar != Input.end() && IsDelimiter(*SrcChar); ++SrcChar )
+ DelimiterFound = true;
+
+ CommentFound = SkipComment(Input, SrcChar);
+ } while( SrcChar != Input.end() && (DelimiterFound || CommentFound) );
+
+ return SrcChar == Input.end();
+}
+
+inline bool SkipIdentifier(const String &Input, String::const_iterator &SrcChar )
+{
+ if( SrcChar == Input.end() )
+ return true;
+
+ if( isalpha( *SrcChar ) || *SrcChar == '_' )
+ {
+ ++SrcChar;
+ if( SrcChar == Input.end() )
+ return true;
+ }
+ else
+ return false;
+
+ for( ; SrcChar != Input.end() && (isalnum( *SrcChar ) || *SrcChar == '_'); ++SrcChar );
+
+ return SrcChar == Input.end();
+}
+
+
+HLSL2GLSLConverter::HLSL2GLSLConverter( IShaderSourceInputStreamFactory *pSourceStreamFactory ) :
+ m_pSourceStreamFactory(pSourceStreamFactory)
+{
+ // Populate HLSL keywords hash map
+#define DEFINE_KEYWORD(kw)m_HLSLKeywords.insert( std::make_pair( #kw, TokenInfo( TokenType::kw, #kw ) ) )
+ DEFINE_KEYWORD( cbuffer );
+ DEFINE_KEYWORD( Texture1D );
+ DEFINE_KEYWORD( Texture1DArray );
+ DEFINE_KEYWORD( Texture2D );
+ DEFINE_KEYWORD( Texture2DArray );
+ DEFINE_KEYWORD( Texture3D );
+ DEFINE_KEYWORD( TextureCube );
+ DEFINE_KEYWORD( TextureCubeArray );
+ DEFINE_KEYWORD( Texture2DMS );
+ DEFINE_KEYWORD( Texture2DMSArray );
+ DEFINE_KEYWORD( SamplerState );
+ DEFINE_KEYWORD( SamplerComparisonState );
+ DEFINE_KEYWORD( RWTexture1D );
+ DEFINE_KEYWORD( RWTexture1DArray );
+ DEFINE_KEYWORD( RWTexture2D );
+ DEFINE_KEYWORD( RWTexture2DArray );
+ DEFINE_KEYWORD( RWTexture3D );
+#undef DEFINE_KEYWORD
+
+#define DEFINE_BUILTIN_TYPE(Type)m_HLSLKeywords.insert( std::make_pair( #Type, TokenInfo( TokenType::BuiltInType, #Type ) ) )
+ DEFINE_BUILTIN_TYPE( void );
+
+ DEFINE_BUILTIN_TYPE( float4 );
+ DEFINE_BUILTIN_TYPE( float3 );
+ DEFINE_BUILTIN_TYPE( float2 );
+ DEFINE_BUILTIN_TYPE( float );
+
+ DEFINE_BUILTIN_TYPE( int4 );
+ DEFINE_BUILTIN_TYPE( int3 );
+ DEFINE_BUILTIN_TYPE( int2 );
+ DEFINE_BUILTIN_TYPE( int );
+
+ DEFINE_BUILTIN_TYPE( uint4 );
+ DEFINE_BUILTIN_TYPE( uint3 );
+ DEFINE_BUILTIN_TYPE( uint2 );
+ DEFINE_BUILTIN_TYPE( uint );
+
+ DEFINE_BUILTIN_TYPE( bool4 );
+ DEFINE_BUILTIN_TYPE( bool3 );
+ DEFINE_BUILTIN_TYPE( bool2 );
+ DEFINE_BUILTIN_TYPE( bool );
+
+ DEFINE_BUILTIN_TYPE( float2x2 );
+ DEFINE_BUILTIN_TYPE( float2x3 );
+ DEFINE_BUILTIN_TYPE( float2x4 );
+
+ DEFINE_BUILTIN_TYPE( float3x2 );
+ DEFINE_BUILTIN_TYPE( float3x3 );
+ DEFINE_BUILTIN_TYPE( float3x4 );
+
+ DEFINE_BUILTIN_TYPE( float4x2 );
+ DEFINE_BUILTIN_TYPE( float4x3 );
+ DEFINE_BUILTIN_TYPE( float4x4 );
+ DEFINE_BUILTIN_TYPE( matrix );
+#undef DEFINE_BUILTIN_TYPE
+
+ m_HLSLKeywords.insert( std::make_pair( "struct", TokenInfo( TokenType::_struct, "struct" ) ) );
+
+#define DEFINE_FLOW_CONTROL_STATEMENT(Statement) m_HLSLKeywords.insert( std::make_pair( #Statement, TokenInfo( TokenType::FlowControl, #Statement ) ) )
+ DEFINE_FLOW_CONTROL_STATEMENT( break );
+ DEFINE_FLOW_CONTROL_STATEMENT( continue );
+ DEFINE_FLOW_CONTROL_STATEMENT( discard );
+ DEFINE_FLOW_CONTROL_STATEMENT( do );
+ DEFINE_FLOW_CONTROL_STATEMENT( for );
+ DEFINE_FLOW_CONTROL_STATEMENT( if );
+ DEFINE_FLOW_CONTROL_STATEMENT( else );
+ DEFINE_FLOW_CONTROL_STATEMENT( switch );
+ DEFINE_FLOW_CONTROL_STATEMENT( while );
+ DEFINE_FLOW_CONTROL_STATEMENT( return );
+#undef DEFINE_FLOW_CONTROL_STATEMENT
+
+
+ // Prepare texture function stubs
+ // sampler usampler isampler sampler*Shadow
+ const String Prefixes[] = { "", "u", "i", "" };
+ const String Suffixes[] = { "", "", "", "Shadow" };
+ for( int i = 0; i < _countof( Prefixes ); ++i )
+ {
+ const auto &Pref = Prefixes[i];
+ const auto &Suff = Suffixes[i];
+ // GetDimensions() does not return anything, so swizzle should be empty
+#define DEFINE_GET_DIM_STUB(Name, Obj, NumArgs) m_GLSLStubs.emplace( make_pair( FunctionStubHashKey( Pref + Obj + Suff, "GetDimensions", NumArgs ), GLSLStubInfo(Name, "") ) )
+
+ DEFINE_GET_DIM_STUB( "GetTex1DDimensions_1", "sampler1D", 1 ); // GetDimensions( Width )
+ DEFINE_GET_DIM_STUB( "GetTex1DDimensions_3", "sampler1D", 3 ); // GetDimensions( Mip, Width, NumberOfMips )
+
+ DEFINE_GET_DIM_STUB( "GetTex1DArrDimensions_2", "sampler1DArray", 2 ); // GetDimensions( Width, ArrElems )
+ DEFINE_GET_DIM_STUB( "GetTex1DArrDimensions_4", "sampler1DArray", 4 ); // GetDimensions( Mip, Width, ArrElems, NumberOfMips )
+
+ DEFINE_GET_DIM_STUB( "GetTex2DDimensions_2", "sampler2D", 2 ); // GetDimensions( Width, Height )
+ DEFINE_GET_DIM_STUB( "GetTex2DDimensions_4", "sampler2D", 4 ); // GetDimensions( Mip, Width, Height, NumberOfMips );
+
+ DEFINE_GET_DIM_STUB( "GetTex2DArrDimensions_3", "sampler2DArray", 3 ); // GetDimensions( Width, Height, ArrElems )
+ DEFINE_GET_DIM_STUB( "GetTex2DArrDimensions_5", "sampler2DArray", 5 ); // GetDimensions( Mip, Width, Height, ArrElems, NumberOfMips )
+
+ DEFINE_GET_DIM_STUB( "GetTex2DDimensions_2", "samplerCube", 2 ); // GetDimensions( Width, Height )
+ DEFINE_GET_DIM_STUB( "GetTex2DDimensions_4", "samplerCube", 4 ); // GetDimensions( Mip, Width, Height, NumberOfMips )
+
+ DEFINE_GET_DIM_STUB( "GetTex2DArrDimensions_3", "samplerCubeArray", 3 ); // GetDimensions( Width, Height, ArrElems )
+ DEFINE_GET_DIM_STUB( "GetTex2DArrDimensions_5", "samplerCubeArray", 5 ); // GetDimensions( Mip, Width, Height, ArrElems, NumberOfMips )
+
+ if( Suff == "" )
+ {
+ // No shadow samplers for Tex3D, Tex2DMS and Tex2DMSArr
+ DEFINE_GET_DIM_STUB( "GetTex3DDimensions_3", "sampler3D", 3 ); // GetDimensions( Width, Height, Depth )
+ DEFINE_GET_DIM_STUB( "GetTex3DDimensions_5", "sampler3D", 5 ); // GetDimensions( Mip, Width, Height, Depth, NumberOfMips )
+
+ DEFINE_GET_DIM_STUB( "GetTex2DMSDimensions_3", "sampler2DMS", 3 ); // GetDimensions( Width, Height, NumSamples )
+ DEFINE_GET_DIM_STUB( "GetTex2DMSArrDimensions_4", "sampler2DMSArray", 4 ); // GetDimensions( Width, Height, ArrElems, NumSamples )
+
+ // Images
+ DEFINE_GET_DIM_STUB( "GetRWTex1DDimensions_1", "image1D", 1 ); // GetDimensions( Width )
+ DEFINE_GET_DIM_STUB( "GetRWTex1DArrDimensions_2", "image1DArray", 2 ); // GetDimensions( Width, ArrElems )
+ DEFINE_GET_DIM_STUB( "GetRWTex2DDimensions_2", "image2D", 2 ); // GetDimensions( Width, Height )
+ DEFINE_GET_DIM_STUB( "GetRWTex2DArrDimensions_3", "image2DArray", 3 ); // GetDimensions( Width, Height, ArrElems )
+ DEFINE_GET_DIM_STUB( "GetRWTex3DDimensions_3", "image3D", 3 ); // GetDimensions( Width, Height, Depth )
+
+ m_ImageTypes.insert( HashMapStringKey(Pref+"image1D") );
+ m_ImageTypes.insert( HashMapStringKey(Pref+"image1DArray") );
+ m_ImageTypes.insert( HashMapStringKey(Pref+"image2D") );
+ m_ImageTypes.insert( HashMapStringKey(Pref+"image2DArray") );
+ m_ImageTypes.insert( HashMapStringKey(Pref+"image3D") );
+ }
+#undef DEFINE_GET_DIM_STUB
+ }
+
+ String Dimensions[] = { "1D", "1DArray", "2D", "2DArray", "3D", "Cube", "CubeArray" };
+ for( int d = 0; d< _countof( Dimensions ); ++d)
+ {
+ String Dim = Dimensions[d];
+ for( int i = 0; i < 3; ++i )
+ {
+ auto GLSLSampler = Prefixes[i] + "sampler" + Dim;
+
+ // Use default swizzle to return the same number of components as specified in the texture declaration
+ // Converter will insert _SWIZZLEn, where n is the number of components, after the function stub.
+ // Example:
+ // Texture2D<float3> Tex2D;
+ // ...
+ // Tex2D.Sample(Tex2D_sampler, f2UV) -> Sample_2(Tex2D, Tex2D_sampler, f2UV)_SWIZZLE3
+ const Char *Swizzle = "_SWIZZLE";
+
+#define DEFINE_STUB(Name, Obj, Func, NumArgs) m_GLSLStubs.emplace( make_pair( FunctionStubHashKey( Obj, Func, NumArgs ), GLSLStubInfo(Name, Swizzle) ) )
+
+ DEFINE_STUB( "Sample_2", GLSLSampler, "Sample", 2 ); // Sample ( Sampler, Location )
+ DEFINE_STUB( "SampleBias_3", GLSLSampler, "SampleBias", 3 ); // SampleBias ( Sampler, Location, Bias )
+ DEFINE_STUB( "SampleLevel_3", GLSLSampler, "SampleLevel", 3 ); // SampleLevel( Sampler, Location, LOD )
+ DEFINE_STUB( "SampleGrad_4", GLSLSampler, "SampleGrad", 4 ); // SampleGrad ( Sampler, Location, DDX, DDY )
+ if( Dim != "Cube" && Dim != "CubeArray" )
+ {
+ // No offset versions for cube & cube array
+ DEFINE_STUB( "Sample_3", GLSLSampler, "Sample", 3 ); // Sample ( Sampler, Location, Offset )
+ DEFINE_STUB( "SampleBias_4", GLSLSampler, "SampleBias", 4 ); // SampleBias ( Sampler, Location, Bias, Offset )
+ DEFINE_STUB( "SampleLevel_4", GLSLSampler, "SampleLevel", 4 ); // SampleLevel( Sampler, Location, LOD, Offset )
+ DEFINE_STUB( "SampleGrad_5", GLSLSampler, "SampleGrad", 5 ); // SampleGrad ( Sampler, Location, DDX, DDY, Offset )
+ }
+ if( Dim != "1D" && Dim != "1DArray" && Dim != "3D" )
+ {
+ // Gather always returns float4 independent of the number of components, so no swizzling
+ Swizzle = "";
+ DEFINE_STUB( "Gather_2", GLSLSampler, "Gather", 2 ); // Gather( SamplerState, Location )
+ DEFINE_STUB( "Gather_3", GLSLSampler, "Gather", 3 ); // Gather( SamplerState, Location, Offset )
+ }
+ }
+ }
+
+ // Gather always returns float4 independent of the number of components, so no swizzling
+ const Char *Swizzle = "";
+ DEFINE_STUB( "GatherCmp_3", "sampler2DShadow", "GatherCmp", 3 ); // GatherCmp( SmplerCmp, Location, CompareValue )
+ DEFINE_STUB( "GatherCmp_4", "sampler2DShadow", "GatherCmp", 4 ); // GatherCmp( SmplerCmp, Location, CompareValue, Offset )
+ DEFINE_STUB( "GatherCmp_3", "sampler2DArrayShadow", "GatherCmp", 3 ); // GatherCmp( SmplerCmp, Location, CompareValue )
+ DEFINE_STUB( "GatherCmp_4", "sampler2DArrayShadow", "GatherCmp", 4 ); // GatherCmp( SmplerCmp, Location, CompareValue, Offset )
+ DEFINE_STUB( "GatherCmp_3", "samplerCubeShadow", "GatherCmp", 3 ); // GatherCmp( SmplerCmp, Location, CompareValue )
+ DEFINE_STUB( "GatherCmp_3", "samplerCubeArrayShadow", "GatherCmp", 3 ); // GatherCmp( SmplerCmp, Location, CompareValue )
+
+ // All load operations should return the same number of components as specified
+ // in texture declaraion, so use swizzling. Example:
+ // Texture3D<int2> Tex3D;
+ // ...
+ // Tex3D.Load(i4Location) -> LoadTex3D_1(Tex3D, i4Location)_SWIZZLE2
+ Swizzle = "_SWIZZLE";
+ for( int i = 0; i < 3; ++i )
+ {
+ auto Pref = Prefixes[i];
+ DEFINE_STUB( "LoadTex1D_1", Pref + "sampler1D", "Load", 1 ); // Load( Location )
+ DEFINE_STUB( "LoadTex1DArr_1", Pref + "sampler1DArray", "Load", 1 ); // Load( Location )
+ DEFINE_STUB( "LoadTex2D_1", Pref + "sampler2D", "Load", 1 ); // Load( Location )
+ DEFINE_STUB( "LoadTex2DArr_1", Pref + "sampler2DArray", "Load", 1 ); // Load( Location )
+ DEFINE_STUB( "LoadTex3D_1", Pref + "sampler3D", "Load", 1 ); // Load( Location )
+ DEFINE_STUB( "LoadTex2DMS_2", Pref + "sampler2DMS", "Load", 2 ); // Load( Location, Sample )
+ DEFINE_STUB( "LoadTex2DMSArr_2", Pref + "sampler2DMSArray", "Load", 2 ); // Load( Location, Sample )
+
+ DEFINE_STUB( "LoadTex1D_2", Pref + "sampler1D", "Load", 2 ); // Load( Location, Offset )
+ DEFINE_STUB( "LoadTex1DArr_2", Pref + "sampler1DArray", "Load", 2 ); // Load( Location, Offset )
+ DEFINE_STUB( "LoadTex2D_2", Pref + "sampler2D", "Load", 2 ); // Load( Location, Offset )
+ DEFINE_STUB( "LoadTex2DArr_2", Pref + "sampler2DArray", "Load", 2 ); // Load( Location, Offset )
+ DEFINE_STUB( "LoadTex3D_2", Pref + "sampler3D", "Load", 2 ); // Load( Location, Offset )
+ DEFINE_STUB( "LoadTex2DMS_3", Pref + "sampler2DMS", "Load", 3 ); // Load( Location, Sample, Offset )
+ DEFINE_STUB( "LoadTex2DMSArr_3", Pref + "sampler2DMSArray", "Load", 3 ); // Load( Location, Sample, Offset )
+
+ DEFINE_STUB( "LoadRWTex1D_1", Pref + "image1D", "Load", 1 ); // Load( Location )
+ DEFINE_STUB( "LoadRWTex1DArr_1", Pref + "image1DArray", "Load", 1 ); // Load( Location )
+ DEFINE_STUB( "LoadRWTex2D_1", Pref + "image2D", "Load", 1 ); // Load( Location )
+ DEFINE_STUB( "LoadRWTex2DArr_1", Pref + "image2DArray", "Load", 1 ); // Load( Location )
+ DEFINE_STUB( "LoadRWTex3D_1", Pref + "image3D", "Load", 1 ); // Load( Location )
+ }
+
+ // SampleCmp() returns float independent of the number of components, so
+ // use no swizzling
+ Swizzle = "";
+
+ DEFINE_STUB( "SampleCmpTex1D_3", "sampler1DShadow", "SampleCmp", 3 ); // SampleCmp( SamplerCmp, Location, CompareValue )
+ DEFINE_STUB( "SampleCmpTex1DArr_3", "sampler1DArrayShadow", "SampleCmp", 3 ); // SampleCmp( SamplerCmp, Location, CompareValue )
+ DEFINE_STUB( "SampleCmpTex2D_3", "sampler2DShadow", "SampleCmp", 3 ); // SampleCmp( SamplerCmp, Location, CompareValue )
+ DEFINE_STUB( "SampleCmpTex2DArr_3", "sampler2DArrayShadow", "SampleCmp", 3 ); // SampleCmp( SamplerCmp, Location, CompareValue )
+ DEFINE_STUB( "SampleCmpTexCube_3", "samplerCubeShadow", "SampleCmp", 3 ); // SampleCmp( SamplerCmp, Location, CompareValue )
+ DEFINE_STUB( "SampleCmpTexCubeArr_3", "samplerCubeArrayShadow","SampleCmp", 3 ); // SampleCmp( SamplerCmp, Location, CompareValue )
+
+ DEFINE_STUB( "SampleCmpTex1D_4", "sampler1DShadow", "SampleCmp", 4 ); // SampleCmp( SamplerCmp, Location, CompareValue, Offset )
+ DEFINE_STUB( "SampleCmpTex1DArr_4", "sampler1DArrayShadow", "SampleCmp", 4 ); // SampleCmp( SamplerCmp, Location, CompareValue, Offset )
+ DEFINE_STUB( "SampleCmpTex2D_4", "sampler2DShadow", "SampleCmp", 4 ); // SampleCmp( SamplerCmp, Location, CompareValue, Offset )
+ DEFINE_STUB( "SampleCmpTex2DArr_4", "sampler2DArrayShadow", "SampleCmp", 4 ); // SampleCmp( SamplerCmp, Location, CompareValue, Offset )
+
+
+ DEFINE_STUB( "SampleCmpLevel0Tex1D_3", "sampler1DShadow", "SampleCmpLevelZero", 3 ); // SampleCmpLevelZero( SamplerCmp, Location, CompareValue )
+ DEFINE_STUB( "SampleCmpLevel0Tex1DArr_3", "sampler1DArrayShadow", "SampleCmpLevelZero", 3 ); // SampleCmpLevelZero( SamplerCmp, Location, CompareValue )
+ DEFINE_STUB( "SampleCmpLevel0Tex2D_3", "sampler2DShadow", "SampleCmpLevelZero", 3 ); // SampleCmpLevelZero( SamplerCmp, Location, CompareValue )
+ DEFINE_STUB( "SampleCmpLevel0Tex2DArr_3", "sampler2DArrayShadow", "SampleCmpLevelZero", 3 ); // SampleCmpLevelZero( SamplerCmp, Location, CompareValue )
+ DEFINE_STUB( "SampleCmpLevel0TexCube_3", "samplerCubeShadow", "SampleCmpLevelZero", 3 ); // SampleCmpLevelZero( SamplerCmp, Location, CompareValue )
+ DEFINE_STUB( "SampleCmpLevel0TexCubeArr_3", "samplerCubeArrayShadow","SampleCmpLevelZero", 3 ); // SampleCmpLevelZero( SamplerCmp, Location, CompareValue )
+
+ DEFINE_STUB( "SampleCmpLevel0Tex1D_4", "sampler1DShadow", "SampleCmpLevelZero", 4 ); // SampleCmpLevelZero( SamplerCmp, Location, CompareValue, Offset )
+ DEFINE_STUB( "SampleCmpLevel0Tex1DArr_4", "sampler1DArrayShadow", "SampleCmpLevelZero", 4 ); // SampleCmpLevelZero( SamplerCmp, Location, CompareValue, Offset )
+ DEFINE_STUB( "SampleCmpLevel0Tex2D_4", "sampler2DShadow", "SampleCmpLevelZero", 4 ); // SampleCmpLevelZero( SamplerCmp, Location, CompareValue, Offset )
+ DEFINE_STUB( "SampleCmpLevel0Tex2DArr_4", "sampler2DArrayShadow", "SampleCmpLevelZero", 4 ); // SampleCmpLevelZero( SamplerCmp, Location, CompareValue, Offset )
+
+
+ // InterlockedOp( dest, val )
+ // InterlockedOp( dest, val, original_val )
+#define DEFINE_ATOMIC_OP_STUBS(Op)\
+ DEFINE_STUB( "Interlocked" Op "SharedVar_2", "shared_var", "Interlocked" Op, 2 ); \
+ DEFINE_STUB( "Interlocked" Op "SharedVar_3", "shared_var", "Interlocked" Op, 3 ); \
+ DEFINE_STUB( "Interlocked" Op "Image_2", "image", "Interlocked" Op, 2 ); \
+ DEFINE_STUB( "Interlocked" Op "Image_3", "image", "Interlocked" Op, 3 ); \
+ m_AtomicOperations.insert( HashMapStringKey("Interlocked" Op) );
+
+
+ DEFINE_ATOMIC_OP_STUBS( "Add" );
+ DEFINE_ATOMIC_OP_STUBS( "And" );
+ DEFINE_ATOMIC_OP_STUBS( "Exchange" );
+ DEFINE_ATOMIC_OP_STUBS( "Max" );
+ DEFINE_ATOMIC_OP_STUBS( "Min" );
+ DEFINE_ATOMIC_OP_STUBS( "Or" );
+ DEFINE_ATOMIC_OP_STUBS( "Xor" );
+
+ // InterlockedCompareExchange( dest, compare_value, value, original_value )
+ DEFINE_STUB( "InterlockedCompareExchangeSharedVar_4", "shared_var", "InterlockedCompareExchange", 4 );
+ DEFINE_STUB( "InterlockedCompareExchangeImage_4", "image", "InterlockedCompareExchange", 4 );
+ m_AtomicOperations.insert( HashMapStringKey("InterlockedCompareExchange") );
+
+ // InterlockedCompareStore( dest, compare_value, value )
+ DEFINE_STUB( "InterlockedCompareStoreSharedVar_3", "shared_var", "InterlockedCompareStore", 3 );
+ DEFINE_STUB( "InterlockedCompareStoreImage_3", "image", "InterlockedCompareStore", 3 );
+ m_AtomicOperations.insert( HashMapStringKey("InterlockedCompareStore") );
+
+#undef DEFINE_STUB
+}
+
+String CompressNewLines( const String& Str )
+{
+ String Out;
+ auto Char = Str.begin();
+ while( Char != Str.end() )
+ {
+ if( *Char == '\r' )
+ {
+ ++Char;
+ // Replace \r\n with \n
+ if( Char != Str.end() && *Char == '\n' )
+ {
+ Out.push_back( '\n' );
+ ++Char;
+ }
+ else
+ Out.push_back( '\r' );
+ }
+ else
+ {
+ Out.push_back( *(Char++) );
+ }
+ }
+ return Out;
+}
+
+static Int32 CountNewLines(const String& Str)
+{
+ Int32 NumNewLines = 0;
+ auto Char = Str.begin();
+ while( Char != Str.end() )
+ {
+ if( *Char == '\r' )
+ {
+ ++NumNewLines;
+ ++Char;
+ // \r\n should be counted as one newline
+ if( Char != Str.end() && *Char == '\n' )
+ ++Char;
+ }
+ else
+ {
+ if( *Char == '\n' )
+ ++NumNewLines;
+ ++Char;
+ }
+ }
+ return NumNewLines;
+}
+
+
+// IteratorType may be String::iterator or String::const_iterator.
+// While iterator is convertible to const_iterator,
+// iterator& cannot be converted to const_iterator& (Microsoft compiler allows
+// such conversion, while gcc does not)
+template<typename IteratorType>
+String HLSL2GLSLConverter::PrintTokenContext( IteratorType &TargetToken, Int32 NumAdjacentLines )
+{
+ if( TargetToken == m_Tokens.end() )
+ --TargetToken;
+
+ //\n ++ x ;
+ //\n ++ y ;
+ //\n if ( x != 0 )
+ // ^
+ //\n x += y ;
+ //\n
+ //\n if ( y != 0 )
+ //\n x += 2 ;
+
+ const int NumSepChars = 20;
+ String Ctx(">");
+ for( int i = 0; i < NumSepChars; ++i )Ctx.append( " >" );
+ Ctx.push_back( '\n' );
+
+ // Find first token in the current line
+ auto CurrLineStartToken = TargetToken;
+ Int32 NumLinesAbove = 0;
+ while( CurrLineStartToken != m_Tokens.begin() )
+ {
+ NumLinesAbove += CountNewLines(CurrLineStartToken->Delimiter);
+ if( NumLinesAbove > 0 )
+ break;
+ --CurrLineStartToken;
+ }
+ //\n if( x != 0 )
+ // ^
+
+ // Find first token in the line NumAdjacentLines above
+ auto TopLineStart = CurrLineStartToken;
+ while( TopLineStart != m_Tokens.begin() && NumLinesAbove <= NumAdjacentLines )
+ {
+ --TopLineStart;
+ NumLinesAbove += CountNewLines(TopLineStart->Delimiter);
+ }
+ //\n ++ x ;
+ // ^
+ //\n ++ y ;
+ //\n if ( x != 0 )
+
+ // Write everything from the top line up to the current line start
+ auto Token = TopLineStart;
+ for( ; Token != CurrLineStartToken; ++Token )
+ {
+ Ctx.append( CompressNewLines(Token->Delimiter) );
+ Ctx.append(Token->Literal);
+ }
+
+ //\n if ( x != 0 )
+ // ^
+
+ Int32 NumLinesBelow = 0;
+ String Spaces; // Accumulate whitespaces preceding current token
+ bool AccumWhiteSpaces = true;
+ while( Token != m_Tokens.end() && NumLinesBelow == 0 )
+ {
+ if( AccumWhiteSpaces )
+ {
+ for( const auto &Char : Token->Delimiter )
+ {
+ if( IsNewLine( Char ) )
+ Spaces.clear();
+ else if( Char == '\t' )
+ Spaces.push_back( Char );
+ else
+ Spaces.push_back( ' ' );
+ }
+ }
+
+ // Acumulate spaces until we encounter current token
+ if( Token == TargetToken )
+ AccumWhiteSpaces = false;
+
+ if( AccumWhiteSpaces )
+ Spaces.append( Token->Literal.length(), ' ' );
+
+ Ctx.append( CompressNewLines(Token->Delimiter) );
+ Ctx.append(Token->Literal);
+ ++Token;
+
+ if( Token == m_Tokens.end() )
+ break;
+
+ NumLinesBelow += CountNewLines(Token->Delimiter);
+ }
+
+ // Write ^ on the line below
+ Ctx.push_back( '\n' );
+ Ctx.append( Spaces );
+ Ctx.push_back( '^' );
+
+ // Write NumAdjacentLines lines below current line
+ while( Token != m_Tokens.end() && NumLinesBelow <= NumAdjacentLines )
+ {
+ Ctx.append( CompressNewLines(Token->Delimiter) );
+ Ctx.append(Token->Literal);
+ ++Token;
+
+ if( Token == m_Tokens.end() )
+ break;
+
+ NumLinesBelow += CountNewLines(Token->Delimiter);
+ }
+
+ Ctx.append("\n<");
+ for( int i = 0; i < NumSepChars; ++i )Ctx.append( " <" );
+ Ctx.push_back( '\n' );
+
+ return Ctx;
+}
+
+
+#define VERIFY_PARSER_STATE( Token, Condition, ... )\
+ if( !(Condition) ) \
+ { \
+ Diligent::MsgStream ss; \
+ Diligent::FormatMsg( ss, __VA_ARGS__ ); \
+ LOG_ERROR_AND_THROW( ss.str(), "\n", PrintTokenContext(Token, 4) );\
+ }
+
+template<typename IterType>
+bool SkipPrefix(const Char* RefStr, IterType &begin, IterType end)
+{
+ auto pos = begin;
+ while( *RefStr && pos != end )
+ {
+ if( *(RefStr++) != *(pos++) )
+ return false;
+ }
+ if( *RefStr == 0 )
+ {
+ begin = pos;
+ return true;
+ }
+
+ return false;
+}
+
+// The method scans the source code and replaces
+// all #include directives with the contents of the
+// file. It maintains a set of already parsed includes
+// to avoid double inclusion
+void HLSL2GLSLConverter::InsertIncludes( String &GLSLSource )
+{
+ // Put all the includes into the set to avoid multiple inclusion
+ std::unordered_set<String> ProcessedIncludes;
+
+ do
+ {
+ // Find the first #include statement
+ auto Pos = GLSLSource.begin();
+ auto IncludeStartPos = GLSLSource.end();
+ while( Pos != GLSLSource.end() )
+ {
+ // # include "TestFile.fxh"
+ if( SkipDelimetersAndComments( GLSLSource, Pos ) )
+ break;
+ if( *Pos == '#' )
+ {
+ IncludeStartPos = Pos;
+ // # include "TestFile.fxh"
+ // ^
+ ++Pos;
+ // # include "TestFile.fxh"
+ // ^
+ if( SkipDelimetersAndComments( GLSLSource, Pos ) )
+ {
+ // End of the file reached - break
+ break;
+ }
+ // # include "TestFile.fxh"
+ // ^
+ if( SkipPrefix( "include", Pos, GLSLSource.end() ) )
+ {
+ // # include "TestFile.fxh"
+ // ^
+ break;
+ }
+ else
+ {
+ // This is not an #include directive:
+ // #define MACRO
+ // Continue search through the file
+ }
+ }
+ else
+ ++Pos;
+ }
+
+ // No more #include found
+ if( Pos == GLSLSource.end() )
+ break;
+
+ // Find open quotes
+ if( SkipDelimetersAndComments( GLSLSource, Pos ) )
+ LOG_ERROR_AND_THROW( "Unexpected EOF after #include directive" );
+ // # include "TestFile.fxh"
+ // ^
+ if( *Pos != '\"' && *Pos != '<' )
+ LOG_ERROR_AND_THROW( "Missing open quotes or \'<\' after #include directive" );
+ ++Pos;
+ // # include "TestFile.fxh"
+ // ^
+ auto IncludeNameStartPos = Pos;
+ // Find closing quotes
+ while( Pos != GLSLSource.end() && *Pos != '\"' && *Pos != '>' )++Pos;
+ // # include "TestFile.fxh"
+ // ^
+ if( Pos == GLSLSource.end() )
+ LOG_ERROR_AND_THROW( "Missing closing quotes or \'>\' after #include directive" );
+
+ // Get the name of the include file
+ auto IncludeName = String( IncludeNameStartPos, Pos );
+ ++Pos;
+ // # include "TestFile.fxh"
+ // ^ ^
+ // IncludeStartPos Pos
+ GLSLSource.erase( IncludeStartPos, Pos );
+
+ // Convert the name to lower case
+ String IncludeFileLowercase = IncludeName;
+ std::transform( IncludeFileLowercase.begin(), IncludeFileLowercase.end(), IncludeFileLowercase.begin(), ::tolower );
+ // Insert the lower-case name into the set
+ auto It = ProcessedIncludes.insert( IncludeFileLowercase );
+ // If the name was actually inserted, which means the include encountered for the first time,
+ // replace the text with the file content
+ if( It.second )
+ {
+ RefCntAutoPtr<IFileStream> pIncludeDataStream;
+ m_pSourceStreamFactory->CreateInputStream( IncludeName.c_str(), &pIncludeDataStream );
+ if( !pIncludeDataStream )
+ LOG_ERROR_AND_THROW( "Failed to open include file ", IncludeName )
+ RefCntAutoPtr<Diligent::IDataBlob> pIncludeData( new Diligent::DataBlobImpl );
+ pIncludeDataStream->Read( pIncludeData );
+
+ // Get include text
+ auto IncludeText = reinterpret_cast<const Char*> (pIncludeData->GetDataPtr());
+ size_t NumSymbols = pIncludeData->GetSize();
+
+ // Insert the text into source
+ GLSLSource.insert( IncludeStartPos-GLSLSource.begin(), IncludeText, NumSymbols );
+ }
+ } while( true );
+}
+
+
+void ReadNumericConstant(const String &Source, String::const_iterator &Pos, String &Output)
+{
+#define COPY_SYMBOL(){ Output.push_back( *(Pos++) ); if( Pos == Source.end() )return; }
+
+ while( Pos != Source.end() && *Pos >= '0' && *Pos <= '9' )
+ COPY_SYMBOL()
+
+ if( *Pos == '.' )
+ {
+ COPY_SYMBOL()
+ // Copy all numbers
+ while( Pos != Source.end() && *Pos >= '0' && *Pos <= '9' )
+ COPY_SYMBOL()
+ }
+
+ // Scientific notation
+ // e+1242, E-234
+ if( *Pos == 'e' || *Pos == 'E' )
+ {
+ COPY_SYMBOL()
+
+ if( *Pos == '+' || *Pos == '-' )
+ COPY_SYMBOL()
+
+ // Skip all numbers
+ while( Pos != Source.end() && *Pos >= '0' && *Pos <= '9' )
+ COPY_SYMBOL()
+ }
+
+ if( *Pos == 'f' || *Pos == 'F' )
+ COPY_SYMBOL()
+#undef COPY_SYMBOL
+}
+
+
+// The function convertes source code into a token list
+void HLSL2GLSLConverter::Tokenize( const String &Source )
+{
+#define CHECK_END(...) \
+ if( SrcPos == Source.end() ) \
+ { \
+ LOG_ERROR_MESSAGE(__VA_ARGS__) \
+ break; \
+ }
+
+ int OpenBracketCount = 0;
+ int OpenBraceCount = 0;
+ int OpenStapleCount = 0;
+
+ // Push empty node in the beginning of the list to facilitate
+ // backwards searching
+ m_Tokens.push_back( TokenInfo() );
+
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/bb509638(v=vs.85).aspx
+
+ // Notes:
+ // * Operators +, - are not detected
+ // * This might be a + b, -a or -10
+ // * Operator ?: is not detected
+ auto SrcPos = Source.begin();
+ while( SrcPos != Source.end() )
+ {
+ TokenInfo NewToken;
+ auto DelimStart = SrcPos;
+ SkipDelimetersAndComments( Source, SrcPos );
+ if( DelimStart != SrcPos )
+ {
+ auto DelimSize = SrcPos - DelimStart;
+ NewToken.Delimiter.reserve(DelimSize);
+ NewToken.Delimiter.append(DelimStart, SrcPos);
+ }
+ if( SrcPos == Source.end() )
+ break;
+
+ switch( *SrcPos )
+ {
+ case '#':
+ {
+ NewToken.Type = TokenType::PreprocessorDirective;
+ auto DirectiveStart = SrcPos;
+ ++SrcPos;
+ SkipDelimetersAndComments( Source, SrcPos );
+ CHECK_END( "Missing preprocessor directive" );
+ SkipIdentifier( Source, SrcPos );
+ auto DirectiveSize = SrcPos - DirectiveStart;
+ NewToken.Literal.reserve(DirectiveSize);
+ NewToken.Literal.append(DirectiveStart, SrcPos);
+ }
+ break;
+
+ case ';':
+ NewToken.Type = TokenType::Semicolon;
+ NewToken.Literal.push_back( *(SrcPos++) );
+ break;
+
+ case '=':
+ if( m_Tokens.size() > 0 && NewToken.Delimiter == "" )
+ {
+ auto &LastToken = m_Tokens.back();
+ // +=, -=, *=, /=, %=, <<=, >>=, &=, |=, ^=
+ if( LastToken.Literal == "+" ||
+ LastToken.Literal == "-" ||
+ LastToken.Literal == "*" ||
+ LastToken.Literal == "/" ||
+ LastToken.Literal == "%" ||
+ LastToken.Literal == "<<" ||
+ LastToken.Literal == ">>" ||
+ LastToken.Literal == "&" ||
+ LastToken.Literal == "|" ||
+ LastToken.Literal == "^")
+ {
+ LastToken.Type = TokenType::Assignment;
+ LastToken.Literal.push_back( *(SrcPos++) );
+ continue;
+ }
+ else if( LastToken.Literal == "<" ||
+ LastToken.Literal == ">" ||
+ LastToken.Literal == "=" ||
+ LastToken.Literal == "!" )
+ {
+ LastToken.Type = TokenType::ComparisonOp;
+ LastToken.Literal.push_back( *(SrcPos++) );
+ continue;
+ }
+ }
+
+ NewToken.Type = TokenType::Assignment;
+ NewToken.Literal.push_back( *(SrcPos++) );
+ break;
+
+ case '|':
+ case '&':
+ if( m_Tokens.size() > 0 && NewToken.Delimiter == "" &&
+ m_Tokens.back().Literal.length() == 1 && m_Tokens.back().Literal[0] == *SrcPos )
+ {
+ m_Tokens.back().Type = TokenType::BooleanOp;
+ m_Tokens.back().Literal.push_back( *(SrcPos++) );
+ continue;
+ }
+ else
+ {
+ NewToken.Type = TokenType::BitwiseOp;
+ NewToken.Literal.push_back( *(SrcPos++) );
+ }
+ break;
+
+ case '<':
+ case '>':
+ if( m_Tokens.size() > 0 && NewToken.Delimiter == "" &&
+ m_Tokens.back().Literal.length() == 1 && m_Tokens.back().Literal[0] == *SrcPos )
+ {
+ m_Tokens.back().Type = TokenType::BitwiseOp;
+ m_Tokens.back().Literal.push_back( *(SrcPos++) );
+ continue;
+ }
+ else
+ {
+ // Note: we do not distinguish between comparison operators
+ // and template arguments like in Texture2D<float> at this
+ // point. This will be clarified when textures are processed.
+ NewToken.Type = TokenType::ComparisonOp;
+ NewToken.Literal.push_back( *(SrcPos++) );
+ }
+ break;
+
+ case '+':
+ case '-':
+ if( m_Tokens.size() > 0 && NewToken.Delimiter == "" &&
+ m_Tokens.back().Literal.length() == 1 && m_Tokens.back().Literal[0] == *SrcPos )
+ {
+ m_Tokens.back().Type = TokenType::IncDecOp;
+ m_Tokens.back().Literal.push_back( *(SrcPos++) );
+ continue;
+ }
+ else
+ {
+ // We do not currently distinguish between math operator a + b,
+ // unary operator -a and numerical constant -1:
+ NewToken.Literal.push_back( *(SrcPos++) );
+ }
+ break;
+
+ case '~':
+ case '^':
+ NewToken.Type = TokenType::BitwiseOp;
+ NewToken.Literal.push_back( *(SrcPos++) );
+ break;
+
+ case '*':
+ case '/':
+ case '%':
+ NewToken.Type = TokenType::MathOp;
+ NewToken.Literal.push_back( *(SrcPos++) );
+ break;
+
+ case '!':
+ NewToken.Type = TokenType::BooleanOp;
+ NewToken.Literal.push_back( *(SrcPos++) );
+ break;
+
+ case ',':
+ NewToken.Type = TokenType::Comma;
+ NewToken.Literal.push_back( *(SrcPos++) );
+ break;
+
+#define BRACKET_CASE(Symbol, TokenType, Action) \
+ case Symbol: \
+ NewToken.Type = TokenType; \
+ NewToken.Literal.push_back( *(SrcPos++) ); \
+ Action; \
+ break;
+ BRACKET_CASE( '(', TokenType::OpenBracket, ++OpenBracketCount );
+ BRACKET_CASE( ')', TokenType::ClosingBracket, --OpenBracketCount );
+ BRACKET_CASE( '{', TokenType::OpenBrace, ++OpenBraceCount );
+ BRACKET_CASE( '}', TokenType::ClosingBrace, --OpenBraceCount );
+ BRACKET_CASE( '[', TokenType::OpenStaple, ++OpenStapleCount );
+ BRACKET_CASE( ']', TokenType::ClosingStaple, --OpenStapleCount );
+#undef BRACKET_CASE
+
+
+ default:
+ {
+ auto IdentifierStartPos = SrcPos;
+ SkipIdentifier( Source, SrcPos );
+ if( IdentifierStartPos != SrcPos )
+ {
+ auto IDSize = SrcPos - IdentifierStartPos;
+ NewToken.Literal.reserve( IDSize );
+ NewToken.Literal.append( IdentifierStartPos, SrcPos );
+ auto KeywordIt = m_HLSLKeywords.find(NewToken.Literal.c_str());
+ if( KeywordIt != m_HLSLKeywords.end() )
+ {
+ NewToken.Type = KeywordIt->second.Type;
+ VERIFY( NewToken.Literal == KeywordIt->second.Literal, "Inconsistent literal" );
+ }
+ else
+ {
+ NewToken.Type = TokenType::Identifier;
+ }
+ }
+
+ if( NewToken.Type == TokenType::Undefined )
+ {
+ bool bIsNumericalCostant = *SrcPos >= '0' && *SrcPos <= '9';
+ if( !bIsNumericalCostant && *SrcPos == '.' )
+ {
+ auto NextPos = SrcPos+1;
+ bIsNumericalCostant = NextPos != Source.end() && *NextPos >= '0' && *NextPos <= '9';
+ }
+ if( bIsNumericalCostant )
+ {
+ ReadNumericConstant(Source, SrcPos, NewToken.Literal);
+ NewToken.Type = TokenType::NumericConstant;
+ }
+ }
+
+ if( NewToken.Type == TokenType::Undefined )
+ {
+ NewToken.Literal.push_back( *(SrcPos++) );
+ }
+ // Operators
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/bb509631(v=vs.85).aspx
+ }
+
+ }
+
+ m_Tokens.push_back( NewToken );
+ }
+#undef CHECK_END
+}
+
+void HLSL2GLSLConverter::FindClosingBracket( TokenListType::iterator &Token,
+ const TokenListType::iterator &ScopeEnd,
+ TokenType OpenBracketType,
+ TokenType ClosingBracketType )
+{
+ VERIFY_EXPR( Token->Type == OpenBracketType );
+ ++Token; // Skip open bracket
+ int BracketCount = 1;
+ // Find matching closing bracket
+ while( Token != ScopeEnd )
+ {
+ if( Token->Type == OpenBracketType )
+ ++BracketCount;
+ else if( Token->Type == ClosingBracketType )
+ {
+ --BracketCount;
+ if( BracketCount == 0 )
+ break;
+ }
+ ++Token;
+ }
+ VERIFY_PARSER_STATE( Token, BracketCount == 0, "No matching closing bracket found in the scope" );
+}
+
+// The function replaces cbuffer with uniform and adds semicolon if it is missing after the closing brace:
+// cbuffer
+// {
+// ...
+// }; <- Semicolon must be here
+//
+void HLSL2GLSLConverter::ProcessConstantBuffer( TokenListType::iterator &Token )
+{
+ VERIFY_EXPR( Token->Type == TokenType::cbuffer );
+
+ // Replace "cbuffer" with "uniform"
+ Token->Literal = "uniform";
+ ++Token;
+ // cbuffer CBufferName
+ // ^
+
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "Unexpected EOF after \"cbuffer\" keyword" );
+ VERIFY_PARSER_STATE( Token, Token->Type == TokenType::Identifier, "Identifier expected after \"cbuffer\" keyword" );
+ const auto& CBufferName = Token->Literal;
+
+ ++Token;
+ // cbuffer CBufferName
+ // ^
+ while( Token != m_Tokens.end() && Token->Type != TokenType::OpenBrace )
+ ++Token;
+ // cbuffer CBufferName
+ // {
+ // ^
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "Missing open brace in the definition of cbuffer ", CBufferName );
+
+ // Find closing brace
+ FindClosingBracket( Token, m_Tokens.end(), TokenType::OpenBrace, TokenType::ClosingBrace );
+
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "No matching closing brace found in the definition of cbuffer ", CBufferName );
+ ++Token; // Skip closing brace
+ // cbuffer CBufferName
+ // {
+ // ...
+ // }
+ // int a
+ // ^
+
+ if( Token == m_Tokens.end() || Token->Type != TokenType::Semicolon )
+ {
+ m_Tokens.insert( Token, TokenInfo( TokenType::Semicolon, ";" ) );
+ // cbuffer CBufferName
+ // {
+ // ...
+ // };
+ // int a;
+ // ^
+ }
+}
+
+
+// The function finds all sampler states in the current scope ONLY, and puts them into the
+// hash table. The hash table indicates if the sampler is comparison or not. It is required to
+// match HLSL texture declaration to sampler* or sampler*Shadow.
+//
+// GLSL only allows samplers as uniform variables and function agruments. It does not allow
+// local variables of sampler type. So the two possible scopes the function can process are
+// global scope and the function argument list.
+//
+// Only samplers in the current scope are processed, all samplers in nested scopes are ignored
+//
+// After the function returns, Token points to the end of the scope (m_Tokens.end() for global scope,
+// or closing bracket for the function argument list)
+//
+// Example 1:
+//
+// Token
+// |
+// SamplerState g_Sampler;
+// SamplerComparsionState g_CmpSampler;
+// void Function(in SamplerState in_Sampler)
+// {
+// }
+//
+// SamplersHash = { {g_Sampler, "false"}, { {g_CmpSampler, "true"} }
+//
+// Example 2:
+//
+// SamplerState g_Sampler;
+// SamplerComparsionState g_CmpSampler;
+// Token
+// |
+// void Function(in SamplerState in_Sampler)
+// {
+// }
+//
+// SamplersHash = { {in_Sampler, "false"} }
+//
+void HLSL2GLSLConverter::ParseSamplers( TokenListType::iterator &Token, SamplerHashType &SamplersHash )
+{
+ VERIFY_EXPR( Token->Type == TokenType::OpenBracket || Token->Type == TokenType::OpenBrace || Token == m_Tokens.begin() );
+ Uint32 ScopeDepth = 1;
+ bool IsFunctionArgumentList = Token->Type == TokenType::OpenBracket;
+
+ // Skip scope start symbol, which is either open bracket or m_Tokens.begin()
+ ++Token;
+ while( Token != m_Tokens.end() && ScopeDepth > 0 )
+ {
+ if( Token->Type == TokenType::OpenBracket ||
+ Token->Type == TokenType::OpenBrace )
+ {
+ // Increase scope depth
+ ++ScopeDepth;
+ ++Token;
+ }
+ else if(Token->Type == TokenType::ClosingBracket ||
+ Token->Type == TokenType::ClosingBrace )
+ {
+ // Decrease scope depth
+ --ScopeDepth;
+ if( ScopeDepth == 0 )
+ break;
+ ++Token;
+ }
+ else if( ( Token->Type == TokenType::SamplerState ||
+ Token->Type == TokenType::SamplerComparisonState ) &&
+ // ONLY parse sampler states in the current scope, skip
+ // all nested scopes
+ ScopeDepth == 1 )
+ {
+ const auto &SamplerType = Token->Literal;
+ bool bIsComparison = Token->Type == TokenType::SamplerComparisonState;
+ // SamplerState LinearClamp;
+ // ^
+ ++Token;
+
+ // There may be a number of samplers declared after single
+ // Sampler[Comparison]State keyword:
+ // SamplerState Tex2D1_sampler, Tex2D2_sampler;
+ do
+ {
+ // SamplerState LinearClamp;
+ // ^
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "Unexpected EOF in ", SamplerType, " declaration" );
+ VERIFY_PARSER_STATE( Token, Token->Type == TokenType::Identifier, "Missing identifier in ", SamplerType, " declaration" );
+ const auto &SamplerName = Token->Literal;
+
+ // Add sampler state into the hash map
+ SamplersHash.insert( std::make_pair( SamplerName, bIsComparison ) );
+
+ ++Token;
+ // SamplerState LinearClamp ;
+ // ^
+
+ // We cannot just remove sampler declarations, because samplers can
+ // be passed to functions as arguments.
+ // SamplerState and SamplerComparisonState are #defined as int, so all
+ // sampler variables will just be unused global variables or function parameters.
+ // Hopefully GLSL compiler will be able to optimize them out.
+
+ if( IsFunctionArgumentList )
+ {
+ // In function argument list, every arument
+ // has its own type declaration
+ break;
+ }
+
+ // Go to the next sampler declaraion or statement end
+ while( Token != m_Tokens.end() && Token->Type != TokenType::Comma && Token->Type != TokenType::Semicolon )
+ ++Token;
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "Unexpected EOF while parsing ", SamplerType, " declaration" );
+
+ if( Token->Type == TokenType::Comma )
+ {
+ // SamplerState Tex2D1_sampler, Tex2D2_sampler ;
+ // ^
+ ++Token;
+ // SamplerState Tex2D1_sampler, Tex2D2_sampler ;
+ // ^
+ }
+ else
+ {
+ // SamplerState Tex2D1_sampler, Tex2D2_sampler ;
+ // ^
+ break;
+ }
+ }while( Token != m_Tokens.end() );
+ }
+ else
+ ++Token;
+ }
+ VERIFY_PARSER_STATE( Token, ScopeDepth == 1 && Token == m_Tokens.end() || ScopeDepth == 0, "Error parsing scope" );
+}
+
+void ParseImageFormat(const String &Comment, String& ImageFormat)
+{
+ // /* format = r32f */
+ // ^
+ auto Pos = Comment.begin();
+ if( SkipDelimeters( Comment, Pos ) )
+ return;
+ // /* format = r32f */
+ // ^
+ if( *Pos != '/' )
+ return;
+ ++Pos;
+ // /* format = r32f */
+ // ^
+ // // format = r32f
+ // ^
+ if( Pos == Comment.end() || (*Pos != '/' && *Pos != '*') )
+ return;
+ ++Pos;
+ // /* format = r32f */
+ // ^
+ if( SkipDelimeters( Comment, Pos ) )
+ return;
+ // /* format = r32f */
+ // ^
+ if( !SkipPrefix( "format", Pos, Comment.end() ) )
+ return;
+ // /* format = r32f */
+ // ^
+ if( SkipDelimeters( Comment, Pos ) )
+ return;
+ // /* format = r32f */
+ // ^
+ if( *Pos != '=' )
+ return;
+ ++Pos;
+ // /* format = r32f */
+ // ^
+ if( SkipDelimeters( Comment, Pos ) )
+ return;
+ // /* format = r32f */
+ // ^
+
+ auto ImgFmtStartPos = Pos;
+ SkipIdentifier( Comment, Pos );
+
+ ImageFormat = String( ImgFmtStartPos, Pos );
+}
+
+// The function processes texture declaration that is indicated by Token, converts it to
+// corresponding GLSL sampler type and adds the new sampler into Objects hash map.
+//
+// Samplers is the stack of sampler states found in all nested scopes.
+// GLSL only supports samplers as global uniform variables or function arguments.
+// Consequently, there are two possible levels in Samplers stack:
+// level 0 - global sampler states (always present)
+// level 1 - samplers declared as function arguments (only present when parsing function body)
+//
+// The function uses the following rules to convert HLSL texture declaration into GLSL sampler:
+// - HLSL texture dimension defines GLSL sampler dimension:
+// - Texture2D -> sampler2D
+// - TextureCube -> samplerCube
+// - HLSL texture component type defines GLSL sampler type. If no type is specified, float4 is assumed:
+// - Texture2D<float> -> sampler2D
+// - Texture3D<uint4> -> usampler3D
+// - Texture2DArray<int2> -> isampler2DArray
+// - Texture2D -> sampler2D
+// - To distinguish if sampler should be shadow or not, the function tries to find <Texture Name>_sampler
+// in the provided sampler state stack. If the sampler type is comparison, the texture is converted
+// to shadow sampler. If sampler state is either not comparison or not found, regular sampler is used
+// Examples:
+// - Texture2D g_ShadowMap; -> sampler2DShadow
+// SamplerComparisonState g_ShadowMap_sampler;
+// - Texture2D g_Tex2D; -> sampler2D g_Tex2D;
+// SamplerState g_Tex2D_sampler;
+// Texture3D g_Tex3D; -> sampler3D g_Tex3D;
+//
+void HLSL2GLSLConverter::ProcessTextureDeclaration( TokenListType::iterator &Token,
+ const std::vector<SamplerHashType> &Samplers,
+ ObjectsTypeHashType &Objects )
+{
+ auto TexDeclToken = Token;
+ auto TextureType = TexDeclToken->Type;
+ // Texture2D < float > ... ;
+ // ^
+ bool IsRWTexture =
+ TextureType == TokenType::RWTexture1D ||
+ TextureType == TokenType::RWTexture1DArray ||
+ TextureType == TokenType::RWTexture2D ||
+ TextureType == TokenType::RWTexture2DArray ||
+ TextureType == TokenType::RWTexture3D;
+
+ ++Token;
+ // Texture2D < float > ... ;
+ // ^
+#define CHECK_EOF() VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "Unexpected EOF in ", TexDeclToken->Literal, " declaration" )
+ CHECK_EOF();
+
+ auto TypeDefinitionStart = Token;
+ String GLSLSampler;
+ String LayoutQualifier;
+ Uint32 NumComponents = 0;
+ if( Token->Literal == "<" )
+ {
+ // Fix token type
+ VERIFY_EXPR( Token->Type == TokenType::ComparisonOp );
+ Token->Type = TokenType::OpenAngleBracket;
+
+ ++Token;
+ CHECK_EOF();
+ // Texture2D < float > ... ;
+ // ^
+ auto TexFmtToken = Token;
+ VERIFY_PARSER_STATE( Token, Token->Type == TokenType::BuiltInType, "Texture format type must be built-in type" );
+ if( Token->Literal == "float" || Token->Literal == "float2" ||
+ Token->Literal == "float3" || Token->Literal == "float4" )
+ {
+ if( Token->Literal == "float" )
+ NumComponents = 1;
+ else
+ NumComponents = Token->Literal.back() - '0';
+ }
+ else if( Token->Literal == "int" || Token->Literal == "int2" ||
+ Token->Literal == "int3" || Token->Literal == "int4" )
+ {
+ GLSLSampler.push_back( 'i' );
+ if( Token->Literal == "int" )
+ NumComponents = 1;
+ else
+ NumComponents = Token->Literal.back() - '0';
+ }
+ else if( Token->Literal == "uint" || Token->Literal == "uint2" ||
+ Token->Literal == "uint3" || Token->Literal == "uint4" )
+ {
+ GLSLSampler.push_back( 'u' );
+ if( Token->Literal == "uint" )
+ NumComponents = 1;
+ else
+ NumComponents = Token->Literal.back() - '0';
+ }
+ else
+ {
+ VERIFY_PARSER_STATE( Token, false, Token->Literal, " is not valid texture component type\n"
+ "Only the following texture element types are supported: float[2,3,4], int[2,3,4], uint[2,3,4]");
+ }
+ VERIFY_PARSER_STATE( Token, NumComponents >= 1 && NumComponents <= 4, "Between 1 and 4 components expected, ", NumComponents ," deduced");
+
+ ++Token;
+ CHECK_EOF();
+ // Texture2D < float > ... ;
+ // ^
+ if( (TextureType == TokenType::Texture2DMS ||
+ TextureType == TokenType::Texture2DMSArray ) &&
+ Token->Literal == "," )
+ {
+ // Texture2DMS < float, 4 > ... ;
+ // ^
+ ++Token;
+ CHECK_EOF();
+ // Texture2DMS < float, 4 > ... ;
+ // ^
+ VERIFY_PARSER_STATE( Token, Token->Type == TokenType::NumericConstant, "Number of samples is expected in ", TexDeclToken->Literal, " declaration" );
+
+ // We do not really need the number of samples, so just skip it
+ ++Token;
+ CHECK_EOF();
+ // Texture2DMS < float, 4 > ... ;
+ // ^
+ }
+ VERIFY_PARSER_STATE( Token, Token->Literal == ">", "Missing \">\" in ", TexDeclToken->Literal, " declaration" );
+ // Fix token type
+ VERIFY_EXPR( Token->Type == TokenType::ComparisonOp );
+ Token->Type = TokenType::ClosingAngleBracket;
+
+ if( IsRWTexture )
+ {
+ String ImgFormat;
+ // RWTexture2D<float /* format = r32f */ >
+ // ^
+ ParseImageFormat( Token->Delimiter, ImgFormat );
+ if( ImgFormat.length() == 0 )
+ {
+ // RWTexture2D</* format = r32f */ float >
+ // ^
+ // TexFmtToken
+ ParseImageFormat( TexFmtToken->Delimiter, ImgFormat );
+ }
+
+ if( ImgFormat.length() != 0 )
+ {
+ LayoutQualifier = String("layout(") + ImgFormat + ") ";
+ }
+ }
+
+ ++Token;
+ // Texture2D < float > TexName ;
+ // ^
+ CHECK_EOF();
+ }
+
+ if( IsRWTexture )
+ GLSLSampler.append( "image" );
+ else
+ GLSLSampler.append( "sampler" );
+
+ switch( TextureType )
+ {
+ case TokenType::RWTexture1D:
+ case TokenType::Texture1D: GLSLSampler += "1D"; break;
+
+ case TokenType::RWTexture1DArray:
+ case TokenType::Texture1DArray: GLSLSampler += "1DArray"; break;
+
+ case TokenType::RWTexture2D:
+ case TokenType::Texture2D: GLSLSampler += "2D"; break;
+
+ case TokenType::RWTexture2DArray:
+ case TokenType::Texture2DArray: GLSLSampler += "2DArray"; break;
+
+ case TokenType::RWTexture3D:
+ case TokenType::Texture3D: GLSLSampler += "3D"; break;
+
+ case TokenType::TextureCube: GLSLSampler += "Cube"; break;
+ case TokenType::TextureCubeArray: GLSLSampler += "CubeArray"; break;
+ case TokenType::Texture2DMS: GLSLSampler += "2DMS"; break;
+ case TokenType::Texture2DMSArray: GLSLSampler += "2DMSArray"; break;
+ default: UNEXPECTED("Unexpected texture type");
+ }
+
+ // TypeDefinitionStart
+ // |
+ // Texture2D < float > TexName ;
+ // ^
+ m_Tokens.erase( TypeDefinitionStart, Token );
+ // Texture2D TexName ;
+ // ^
+
+ bool IsGlobalScope = Samplers.size() == 1;
+
+ // There may be more than one texture variable declared in the same
+ // statement:
+ // Texture2D<float> g_Tex2D1, g_Tex2D1;
+ do
+ {
+ // Texture2D TexName ;
+ // ^
+ VERIFY_PARSER_STATE( Token, Token->Type == TokenType::Identifier, "Identifier expected in ", TexDeclToken->Literal, " declaration" );
+
+ // Make sure there is a delimiter between sampler keyword and the
+ // identifier. In cases like this
+ // Texture2D<float>Name;
+ // There will be no whitespace
+ if( Token->Delimiter == "" )
+ Token->Delimiter = " ";
+
+ // Texture2D TexName ;
+ // ^
+ const auto &TextureName = Token->Literal;
+
+ auto CompleteGLSLSampler = GLSLSampler;
+ if( !IsRWTexture )
+ {
+ // Try to find matching sampler
+ auto SamplerName = TextureName + "_sampler";
+ // Search all scopes starting with the innermost
+ for( auto ScopeIt = Samplers.rbegin(); ScopeIt != Samplers.rend(); ++ScopeIt )
+ {
+ auto SamplerIt = ScopeIt->find( SamplerName );
+ if( SamplerIt != ScopeIt->end() )
+ {
+ if( SamplerIt->second )
+ CompleteGLSLSampler.append( "Shadow" );
+ break;
+ }
+ }
+ }
+
+ // TexDeclToken
+ // |
+ // Texture2D TexName ;
+ // ^
+ TexDeclToken->Literal = "";
+ TexDeclToken->Literal.append( LayoutQualifier );
+ if( IsGlobalScope )
+ {
+ // Samplers and images in global scope must be declared uniform.
+ // Function arguments must not be declared uniform
+ TexDeclToken->Literal.append( "uniform " );
+ }
+ TexDeclToken->Literal.append( CompleteGLSLSampler );
+ Objects.insert( std::make_pair( HashMapStringKey(TextureName), HLSLObjectInfo(CompleteGLSLSampler, NumComponents) ) );
+
+ // In global sceop, multiple variables can be declared in the same statement
+ if( IsGlobalScope )
+ {
+ // Texture2D TexName, TexName2 ;
+ // ^
+
+ // Go to the next texture in the declaration or to the statement end
+ while( Token != m_Tokens.end() && Token->Type != TokenType::Comma && Token->Type != TokenType::Semicolon )
+ ++Token;
+ if( Token->Type == TokenType::Comma )
+ {
+ // Texture2D TexName, TexName2 ;
+ // ^
+ Token->Type = TokenType::Semicolon;
+ Token->Literal = ";";
+ // Texture2D TexName; TexName2 ;
+ // ^
+
+ ++Token;
+ // Texture2D TexName; TexName2 ;
+ // ^
+
+ // Insert empty token that will contain next sampler/image declaration
+ TexDeclToken = m_Tokens.insert( Token, TokenInfo(TextureType, "", "\n") );
+ // Texture2D TexName;
+ // <Texture Declaration TBD> TexName2 ;
+ // ^ ^
+ // TexDeclToken Token
+ }
+ else
+ {
+ // Texture2D TexName, TexName2 ;
+ // ^
+ ++Token;
+ break;
+ }
+ }
+
+ } while( IsGlobalScope && Token != m_Tokens.end() );
+
+#undef SKIP_DELIMITER
+#undef CHECK_EOF
+}
+
+
+// Finds an HLSL object with the given name in object stack
+const HLSL2GLSLConverter::HLSLObjectInfo *HLSL2GLSLConverter::FindHLSLObject( const String &Name )
+{
+ for( auto ScopeIt = m_Objects.rbegin(); ScopeIt != m_Objects.rend(); ++ScopeIt )
+ {
+ auto It = ScopeIt->find( Name.c_str() );
+ if( It != ScopeIt->end() )
+ return &It->second;
+ }
+ return nullptr;
+}
+
+Uint32 HLSL2GLSLConverter::CountFunctionArguments( TokenListType::iterator &Token, const TokenListType::iterator &ScopeEnd )
+{
+ Uint32 NumArguments = 0;
+ int NumOpenBrackets = 1;
+ ++Token;
+ while( Token != ScopeEnd && NumOpenBrackets != 0 )
+ {
+ // Do not count arguments of nested functions:
+ // TestText.Sample( TestText_sampler, float2(0.0, 1.0) );
+ // ^
+ // NumOpenBrackets == 2
+ if( NumOpenBrackets == 1 && (Token->Literal == "," || Token->Type == TokenType::ClosingBracket) )
+ ++NumArguments;
+
+ if( Token->Type == TokenType::OpenBracket )
+ ++NumOpenBrackets;
+ else if( Token->Type == TokenType::ClosingBracket )
+ --NumOpenBrackets;
+
+ ++Token;
+ }
+ return NumArguments;
+}
+
+// The function processes HLSL object method in current scope and replaces it
+// with the corresponding GLSL function stub
+// Example:
+// Texture2D<float2> Tex2D;
+// ...
+// Tex2D.Sample(Tex2D_sampler, f2UV) -> Sample_2(Tex2D, Tex2D_sampler, f2UV)_SWIZZLE2
+bool HLSL2GLSLConverter::ProcessObjectMethod(TokenListType::iterator &Token,
+ const TokenListType::iterator &ScopeStart,
+ const TokenListType::iterator &ScopeEnd)
+{
+ // TestText.Sample( ...
+ // ^
+ // DotToken
+ auto DotToken = Token;
+ VERIFY_EXPR(DotToken != ScopeEnd && Token->Literal == ".");
+ auto MethodToken = DotToken;
+ ++MethodToken;
+ VERIFY_EXPR( MethodToken != ScopeEnd && MethodToken->Type == TokenType::Identifier);
+ // TestText.Sample( ...
+ // ^
+ // MethodToken
+ auto IdentifierToken = DotToken;
+ // m_Tokens contains dummy node at the beginning, so we can
+ // check for ScopeStart to break the loop
+ while( IdentifierToken != ScopeStart && IdentifierToken->Type != TokenType::Identifier)
+ --IdentifierToken;
+ if( IdentifierToken == ScopeStart )
+ return false;
+ // TestTextArr[2].Sample( ...
+ // ^
+ // IdentifierToken
+
+ // Try to find identifier
+ const auto *pObjectInfo = FindHLSLObject(IdentifierToken->Literal);
+ if( pObjectInfo == nullptr )
+ {
+ return false;
+ }
+ const auto &ObjectType = pObjectInfo->GLSLType;
+
+ auto ArgsListStartToken = MethodToken;
+ ++ArgsListStartToken;
+
+ // TestText.Sample( ...
+ // ^
+ // ArgsListStartToken
+
+ if( ArgsListStartToken == ScopeEnd || ArgsListStartToken->Type != TokenType::OpenBracket )
+ return false;
+ auto ArgsListEndToken = ArgsListStartToken;
+ Uint32 NumArguments = CountFunctionArguments( ArgsListEndToken, ScopeEnd );
+
+ if( ArgsListEndToken == ScopeEnd )
+ return false;
+ // TestText.Sample( TestText_sampler, float2(0.0, 1.0) );
+ // ^
+ // ArgsListEndToken
+ auto Stub = m_GLSLStubs.find( FunctionStubHashKey(ObjectType, MethodToken->Literal.c_str(), NumArguments) );
+ if( Stub == m_GLSLStubs.end() )
+ {
+ LOG_ERROR_MESSAGE( "Unable to find function stub for ", IdentifierToken->Literal, ".", MethodToken->Literal, "(", NumArguments, " args). GLSL object type: ", ObjectType );
+ return false;
+ }
+
+ // DotToken
+ // V
+ // TestTextArr[2].Sample( TestTextArr_sampler, ...
+ // ^ ^
+ // IdentifierToken ArgsListStartToken
+
+ *ArgsListStartToken = TokenInfo(TokenType::Comma, ",");
+ // TestTextArr[2].Sample, TestTextArr_sampler, ...
+ // ^ ^
+ // DotToken ArgsListStartToken
+
+ m_Tokens.erase(DotToken, ArgsListStartToken);
+ // TestTextArr[2], TestTextArr_sampler, ...
+ // ^
+ // IdentifierToken
+
+ m_Tokens.insert( IdentifierToken, TokenInfo( TokenType::Identifier, Stub->second.Name.c_str(), IdentifierToken->Delimiter.c_str()) );
+ IdentifierToken->Delimiter = " ";
+ // FunctionStub TestTextArr[2], TestTextArr_sampler, ...
+ // ^
+ // IdentifierToken
+
+
+ m_Tokens.insert( IdentifierToken, TokenInfo( TokenType::OpenBracket, "(") );
+ // FunctionStub( TestTextArr[2], TestTextArr_sampler, ...
+ // ^
+ // IdentifierToken
+
+ Token = ArgsListStartToken;
+ // FunctionStub( TestTextArr[2], TestTextArr_sampler, ...
+ // ^
+ // Token
+
+ // Nested function calls will be automatically processed:
+ // FunctionStub( TestTextArr[2], TestTextArr_sampler, TestTex.Sample(...
+ // ^
+ // Token
+
+
+ // Add swizzling if there is any
+ if( Stub->second.Swizzle.length() > 0 )
+ {
+ // FunctionStub( TestTextArr[2], TestTextArr_sampler, ... );
+ // ^
+ // ArgsListEndToken
+
+ auto SwizzleToken = m_Tokens.insert( ArgsListEndToken, TokenInfo(TokenType::TextBlock, Stub->second.Swizzle.c_str(), "") );
+ SwizzleToken->Literal.push_back( '0' + pObjectInfo->NumComponents );
+ // FunctionStub( TestTextArr[2], TestTextArr_sampler, ... )_SWIZZLE4;
+ // ^
+ // ArgsListEndToken
+ }
+ return true;
+}
+
+void HLSL2GLSLConverter::RemoveFlowControlAttribute( TokenListType::iterator &Token )
+{
+ VERIFY_EXPR( Token->Type == TokenType::FlowControl );
+ // [ branch ] if ( ...
+ // ^
+ auto PrevToken = Token;
+ --PrevToken;
+ // [ branch ] if ( ...
+ // ^
+ // Note that dummy empty token is inserted into the beginning of the list
+ if( PrevToken == m_Tokens.begin() || PrevToken->Type != TokenType::ClosingStaple )
+ return;
+
+ --PrevToken;
+ // [ branch ] if ( ...
+ // ^
+ if( PrevToken == m_Tokens.begin() || PrevToken->Type != TokenType::Identifier )
+ return;
+
+ --PrevToken;
+ // [ branch ] if ( ...
+ // ^
+ if( PrevToken == m_Tokens.begin() || PrevToken->Type != TokenType::OpenStaple )
+ return;
+
+ // [ branch ] if ( ...
+ // ^ ^
+ // PrevToken Token
+ Token->Delimiter = PrevToken->Delimiter;
+ m_Tokens.erase( PrevToken, Token );
+}
+
+// The function finds all HLSL object methods in the current scope and calls ProcessObjectMethod()
+// that replaces them with the corresponding GLSL function stub.
+void HLSL2GLSLConverter::ProcessObjectMethods(const TokenListType::iterator &ScopeStart,
+ const TokenListType::iterator &ScopeEnd)
+{
+ auto Token = ScopeStart;
+ while( Token != ScopeEnd )
+ {
+ // Search for .identifier pattern
+
+ if( Token->Literal == "." )
+ {
+ auto DotToken = Token;
+ ++Token;
+ if( Token == ScopeEnd )
+ break;
+ if( Token->Type == TokenType::Identifier )
+ {
+ if( ProcessObjectMethod( DotToken, ScopeStart, ScopeEnd ) )
+ Token = DotToken;
+ }
+ else
+ {
+ ++Token;
+ continue;
+ }
+ }
+ else
+ ++Token;
+ }
+}
+
+// The function processes HLSL RW texture operator [] and replaces it with
+// corresponding imageStore GLSL function.
+// Example:
+// RWTex[Location] = f3Value -> imageStore( RWTex,Location, _ExpandVector(f3Value))
+// _ExpandVector() function expands any input vector to 4-component vector
+bool HLSL2GLSLConverter::ProcessRWTextureStore( TokenListType::iterator &Token,
+ const TokenListType::iterator &ScopeEnd )
+{
+ // RWTex[Location.x] = float4(0.0, 0.0, 0.0, 1.0);
+ // ^
+ auto AssignmentToken = Token;
+ while( AssignmentToken != ScopeEnd &&
+ !(AssignmentToken->Type == TokenType::Assignment || AssignmentToken->Type == TokenType::Semicolon) )
+ ++AssignmentToken;
+
+ // The function is called for ALL RW texture objects found, so this may not be
+ // the store operation, but something else (for instance:
+ // InterlockedExchange(Tex2D_I1[GTid.xy], 1, iOldVal) )
+ if( AssignmentToken == ScopeEnd || AssignmentToken->Type != TokenType::Assignment )
+ return false;
+ // RWTex[Location.x] = float4(0.0, 0.0, 0.0, 1.0);
+ // ^
+ // AssignmentToken
+ auto ClosingStaplePos = AssignmentToken;
+ while( ClosingStaplePos != Token && ClosingStaplePos->Type != TokenType::ClosingStaple )
+ --ClosingStaplePos;
+ if( ClosingStaplePos == Token )
+ return false;
+ // RWTex[Location.x] = float4(0.0, 0.0, 0.0, 1.0);
+ // ^
+ // ClosingStaplePos
+
+ auto OpenStaplePos = ClosingStaplePos;
+ while( OpenStaplePos != Token && OpenStaplePos->Type != TokenType::OpenStaple )
+ --OpenStaplePos;
+ if( OpenStaplePos == Token )
+ return false;
+ // RWTex[Location.x] = float4(0.0, 0.0, 0.0, 1.0);
+ // ^
+ // OpenStaplePos
+
+ auto SemicolonToken = AssignmentToken;
+ while( SemicolonToken != ScopeEnd && SemicolonToken->Type != TokenType::Semicolon )
+ ++SemicolonToken;
+ if( SemicolonToken == ScopeEnd )
+ return false;
+ // RWTex[Location.x] = float4(0.0, 0.0, 0.0, 1.0);
+ // ^ ^
+ // Token SemicolonToken
+
+ m_Tokens.insert( Token, TokenInfo(TokenType::Identifier, "imageStore", Token->Delimiter.c_str()) );
+ m_Tokens.insert( Token, TokenInfo(TokenType::OpenBracket, "(", "" ) );
+ Token->Delimiter = " ";
+ // imageStore( RWTex[Location.x] = float4(0.0, 0.0, 0.0, 1.0);
+
+ OpenStaplePos->Delimiter = "";
+ OpenStaplePos->Type = TokenType::Comma;
+ OpenStaplePos->Literal = ",";
+ // imageStore( RWTex,Location.x] = float4(0.0, 0.0, 0.0, 1.0);
+ // ^
+ // ClosingStaplePos
+
+ auto LocationToken = OpenStaplePos;
+ ++LocationToken;
+ m_Tokens.insert( LocationToken, TokenInfo( TokenType::Identifier, "_ToIvec", " " ) );
+ m_Tokens.insert( LocationToken, TokenInfo( TokenType::OpenBracket, "(", "" ) );
+ // imageStore( RWTex, _ToIvec(Location.x] = float4(0.0, 0.0, 0.0, 1.0);
+ // ^
+ // ClosingStaplePos
+
+ m_Tokens.insert( ClosingStaplePos, TokenInfo( TokenType::ClosingBracket, ")", "" ) );
+ // imageStore( RWTex, _ToIvec(Location.x)] = float4(0.0, 0.0, 0.0, 1.0);
+ // ^
+ // ClosingStaplePos
+
+ ClosingStaplePos->Delimiter = "";
+ ClosingStaplePos->Type = TokenType::Comma;
+ ClosingStaplePos->Literal = ",";
+ // imageStore( RWTex, _ToIvec(Location.x), = float4(0.0, 0.0, 0.0, 1.0);
+ // ^
+ // AssignmentToken
+
+ AssignmentToken->Delimiter = "";
+ AssignmentToken->Type = TokenType::OpenBracket;
+ AssignmentToken->Literal = "(";
+ // imageStore( RWTex, _ToIvec(Location.x),( float4(0.0, 0.0, 0.0, 1.0);
+ // ^
+
+ m_Tokens.insert( AssignmentToken, TokenInfo(TokenType::Identifier, "_ExpandVector", " " ) );
+ // imageStore( RWTex, _ToIvec(Location.x), _ExpandVector( float4(0.0, 0.0, 0.0, 1.0);
+ // ^
+
+ // Insert closing bracket for _ExpandVector
+ m_Tokens.insert( SemicolonToken, TokenInfo(TokenType::ClosingBracket, ")", "" ) );
+ // imageStore( RWTex, _ToIvec(Location.x), _ExpandVector( float4(0.0, 0.0, 0.0, 1.0));
+
+ // Insert closing bracket for imageStore
+ m_Tokens.insert( SemicolonToken, TokenInfo(TokenType::ClosingBracket, ")", "" ) );
+ // imageStore( RWTex, _ToIvec(Location.x), _ExpandVector( float4(0.0, 0.0, 0.0, 1.0)));
+
+ return false;
+}
+
+// Function finds all RW textures in current scope and calls ProcessRWTextureStore()
+// that detects if this is store operation and converts it to imageStore()
+void HLSL2GLSLConverter::ProcessRWTextures(const TokenListType::iterator &ScopeStart,
+ const TokenListType::iterator &ScopeEnd)
+{
+ auto Token = ScopeStart;
+ while( Token != ScopeEnd )
+ {
+ if( Token->Type == TokenType::Identifier )
+ {
+ // Try to find the object in all scopes
+ const auto *pObjectInfo = FindHLSLObject(Token->Literal);
+ if( pObjectInfo == nullptr )
+ {
+ ++Token;
+ continue;
+ }
+
+ // Check if the object is image type
+ auto ImgTypeIt = m_ImageTypes.find( pObjectInfo->GLSLType.c_str() );
+ if( ImgTypeIt == m_ImageTypes.end() )
+ {
+ ++Token;
+ continue;
+ }
+
+ // Handle store. If this is not store operation,
+ // ProcessRWTextureStore() returns false.
+ auto TmpToken = Token;
+ if( ProcessRWTextureStore( TmpToken, ScopeEnd ) )
+ Token = TmpToken;
+ else
+ ++Token;
+ }
+ else
+ ++Token;
+ }
+}
+
+// The function processes all atomic operations in current scope and replaces them with
+// corresponding GLSL function
+void HLSL2GLSLConverter::ProcessAtomics(const TokenListType::iterator &ScopeStart,
+ const TokenListType::iterator &ScopeEnd)
+{
+ auto Token = ScopeStart;
+ while( Token != ScopeEnd )
+ {
+ if( Token->Type == TokenType::Identifier )
+ {
+ auto AtomicIt = m_AtomicOperations.find(Token->Literal.c_str());
+ if( AtomicIt == m_AtomicOperations.end() )
+ {
+ ++Token;
+ continue;
+ }
+
+ auto OperationToken = Token;
+ // InterlockedAdd(g_i4SharedArray[GTid.x].x, 1, iOldVal);
+ // ^
+ ++Token;
+ // InterlockedAdd(g_i4SharedArray[GTid.x].x, 1, iOldVal);
+ // ^
+ VERIFY_PARSER_STATE( Token, Token != ScopeEnd, "Unexpected EOF" );
+ VERIFY_PARSER_STATE( Token, Token->Type == TokenType::OpenBracket, "Open bracket is expected" );
+
+ ++Token;
+ // InterlockedAdd(g_i4SharedArray[GTid.x].x, 1, iOldVal);
+ // ^
+ VERIFY_PARSER_STATE( Token, Token != ScopeEnd, "Unexpected EOF" );
+ VERIFY_PARSER_STATE( Token, Token->Type == TokenType::Identifier, "Identifier is expected" );
+
+ auto ArgsListEndToken = Token;
+ auto NumArguments = CountFunctionArguments( ArgsListEndToken, ScopeEnd );
+ // InterlockedAdd(Tex2D[GTid.xy], 1, iOldVal);
+ // ^
+ // ArgsListEndToken
+ VERIFY_PARSER_STATE( ArgsListEndToken, ArgsListEndToken != ScopeEnd, "Unexpected EOF" );
+
+ const auto *pObjectInfo = FindHLSLObject(Token->Literal);
+ if( pObjectInfo != nullptr )
+ {
+ // InterlockedAdd(Tex2D[GTid.xy], 1, iOldVal);
+ // ^
+ auto Stub = m_GLSLStubs.find( FunctionStubHashKey("image", OperationToken->Literal.c_str(), NumArguments) );
+ VERIFY_PARSER_STATE(OperationToken, Stub != m_GLSLStubs.end(), "Unable to find function stub for funciton ", OperationToken->Literal, " with ", NumArguments, " arguments" );
+
+ // Find first comma
+ int NumOpenBrackets = 1;
+ while( Token != ScopeEnd && NumOpenBrackets != 0 )
+ {
+ // Do not count arguments of nested functions:
+ if( NumOpenBrackets == 1 && (Token->Type == TokenType::Comma || Token->Type == TokenType::ClosingBracket) )
+ break;
+
+ if( Token->Type == TokenType::OpenBracket )
+ ++NumOpenBrackets;
+ else if( Token->Type == TokenType::ClosingBracket )
+ --NumOpenBrackets;
+
+ ++Token;
+ }
+ // InterlockedAdd(Tex2D[GTid.xy], 1, iOldVal);
+ // ^
+ VERIFY_PARSER_STATE( Token, Token != ScopeEnd, "Unexpected EOF" );
+ VERIFY_PARSER_STATE( Token, Token->Type == TokenType::Comma, "Comma is expected" );
+
+ --Token;
+ // InterlockedAdd(Tex2D[GTid.xy], 1, iOldVal);
+ // ^
+ VERIFY_PARSER_STATE( Token, Token->Type == TokenType::ClosingStaple, "Expected \']\'" );
+ auto ClosingBracketToken = Token;
+ --Token;
+ m_Tokens.erase( ClosingBracketToken );
+ // InterlockedAdd(Tex2D[GTid.xy, 1, iOldVal);
+ // ^
+ while( Token != ScopeStart && Token->Type != TokenType::OpenStaple )
+ --Token;
+ // InterlockedAdd(Tex2D[GTid.xy, 1, iOldVal);
+ // ^
+
+ VERIFY_PARSER_STATE( Token, Token != ScopeStart, "Expected \'[\'" );
+ Token->Type = TokenType::Comma;
+ Token->Literal = ",";
+ // InterlockedAdd(Tex2D,GTid.xy, 1, iOldVal);
+ // ^
+
+ OperationToken->Literal = Stub->second.Name;
+ // InterlockedAddImage_3(Tex2D,GTid.xy, 1, iOldVal);
+ }
+ else
+ {
+ // InterlockedAdd(g_i4SharedArray[GTid.x].x, 1, iOldVal);
+ // ^
+ auto Stub = m_GLSLStubs.find( FunctionStubHashKey("shared_var", OperationToken->Literal.c_str(), NumArguments) );
+ VERIFY_PARSER_STATE(OperationToken, Stub != m_GLSLStubs.end(), "Unable to find function stub for funciton ", OperationToken->Literal, " with ", NumArguments, " arguments" );
+ OperationToken->Literal = Stub->second.Name;
+ // InterlockedAddSharedVar_3(g_i4SharedArray[GTid.x].x, 1, iOldVal);
+ }
+ Token = ArgsListEndToken;
+ }
+ else
+ ++Token;
+ }
+}
+
+// The function parses shader arguments and puts them into Params array
+void HLSL2GLSLConverter::ParseShaderParameters( TokenListType::iterator &Token, std::vector<ShaderParameterInfo>& Params )
+{
+ // void TestPS ( in VSOutput In,
+ // ^
+ VERIFY_EXPR(Token->Type == TokenType::OpenBracket);
+ ++Token;
+ // void TestPS ( in VSOutput In,
+ // ^
+ while(Token != m_Tokens.end())
+ {
+ ShaderParameterInfo ParamInfo;
+ if( Token->Literal == "in" )
+ {
+ //void TestPS ( in VSOutput In,
+ // ^
+ ParamInfo.storageQualifier = ShaderParameterInfo::StorageQualifier::In;
+ ++Token;
+ //void TestPS ( in VSOutput In,
+ // ^
+ }
+ else if( Token->Literal == "out" )
+ {
+ // out float4 Color : SV_Target,
+ // ^
+ ParamInfo.storageQualifier = ShaderParameterInfo::StorageQualifier::Out;
+ ++Token;
+ // out float4 Color : SV_Target,
+ // ^
+ }
+ else
+ ParamInfo.storageQualifier = ShaderParameterInfo::StorageQualifier::In;
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "Unexpected EOF while parsing argument list" );
+ VERIFY_PARSER_STATE( Token, Token->Type == TokenType::BuiltInType || Token->Type == TokenType::Identifier,
+ "Missing argument type" );
+
+ ParamInfo.Type = Token->Literal;
+
+ ++Token;
+ // out float4 Color : SV_Target,
+ // ^
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "Unexpected EOF while parsing argument list" );
+ VERIFY_PARSER_STATE( Token, Token->Type == TokenType::Identifier, "Missing argument name after ", ParamInfo.Type );
+ ParamInfo.Name = Token->Literal;
+
+ ++Token;
+ // out float4 Color : SV_Target,
+ // ^
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "Unexpected end of file after argument \"", ParamInfo.Name, '\"' );
+ if( Token->Literal == ":" )
+ {
+ ++Token;
+ // out float4 Color : SV_Target,
+ // ^
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "Unexpected end of file while looking for semantic for argument \"", ParamInfo.Name, '\"' );
+ VERIFY_PARSER_STATE( Token, Token->Type == TokenType::Identifier, "Missing semantic for argument \"", ParamInfo.Name, '\"' );
+ ParamInfo.Semantic = Token->Literal;
+ // Transform to lower case - semantics are case-insensitive
+ std::transform( ParamInfo.Semantic.begin(), ParamInfo.Semantic.end(), ParamInfo.Semantic.begin(), ::tolower );
+
+ ++Token;
+ // out float4 Color : SV_Target,
+ // ^
+ }
+
+ VERIFY_PARSER_STATE( Token, Token->Literal == "," || Token->Type == TokenType::ClosingBracket, "\',\' or \')\' is expected after argument \"", ParamInfo.Name, '\"' );
+ Params.push_back( ParamInfo );
+ if( Token->Type == TokenType::ClosingBracket )
+ break;
+ ++Token;
+ }
+}
+
+void DeclareVariable(const String& Type, const String& Name, const Char* InitValue, bool bForceType, std::stringstream &OutSS)
+{
+ OutSS << Type << ' ' << Name;
+ if( InitValue )
+ {
+ OutSS << " = ";
+ if( bForceType )
+ {
+ OutSS << Type << '(';
+ }
+ OutSS << InitValue;
+ if( bForceType )
+ OutSS << ')';
+ }
+ OutSS << ";\n" ;
+}
+
+void DeclareInterfaceBlock( const Char* Qualifier, Uint32 InterfaceBlockNum, const String& ParamType, const String& ParamName, std::stringstream &OutSS )
+{
+ OutSS << Qualifier <<" _IntererfaceBlock" << InterfaceBlockNum << "\n"
+ "{\n"
+ " " << ParamType << ' ' << ParamName << ";\n"
+ "};\n";
+}
+
+void HLSL2GLSLConverter::ProcessFragmentShaderArguments(std::vector<ShaderParameterInfo>& Params,
+ String &GlobalVariables,
+ String &Epilogue,
+ String &Prologue)
+{
+ stringstream GlobalVarsSS, PrologueSS, EpilogueSS;
+ int InterfaceBlockNum = 0;
+ for( const auto &Param : Params )
+ {
+ if( Param.storageQualifier == ShaderParameterInfo::StorageQualifier::In )
+ {
+ if( Param.Semantic == "" )
+ {
+ DeclareInterfaceBlock( "in", InterfaceBlockNum, Param.Type, Param.Name, GlobalVarsSS );
+ ++InterfaceBlockNum;
+ }
+ else if( Param.Semantic == "sv_position" )
+ {
+ DeclareVariable( Param.Type.c_str(), Param.Name.c_str(), "gl_FragCoord", false, PrologueSS );
+ }
+ else
+ {
+ LOG_ERROR_AND_THROW( "Semantic \"", Param.Semantic, "\" is not supported in a pixel shader." );
+ }
+ }
+ else if( Param.storageQualifier == ShaderParameterInfo::StorageQualifier::Out )
+ {
+ const auto& Semantic = Param.Semantic;
+ auto RTIndexPos = Semantic.begin();
+ int RTIndex = -1;
+ if( SkipPrefix( "sv_target", RTIndexPos, Semantic.end() ) )
+ {
+ if( RTIndexPos != Semantic.end() )
+ {
+ if( *RTIndexPos >= '0' && *RTIndexPos <= '9' )
+ {
+ RTIndex = *RTIndexPos - '0';
+ if( (RTIndexPos + 1) != Semantic.end() )
+ RTIndex = -1;
+ }
+ }
+ else
+ RTIndex = 0;
+ }
+
+ if( RTIndex >= 0 && RTIndex < MaxRenderTargets )
+ {
+ String GlobalVarName = "_out_";
+ GlobalVarName.append( Param.Name );
+
+ GlobalVarsSS << "layout(location = " << RTIndex << ") out "
+ << Param.Type << ' ' << GlobalVarName << ";\n";
+
+ DeclareVariable( Param.Type, Param.Name, nullptr, false, PrologueSS );
+
+ EpilogueSS << GlobalVarName << " = " << Param.Name << ";\n";
+ }
+ else
+ {
+ LOG_ERROR_AND_THROW( "Unexpected output semantic \"", Semantic, "\". The only allowed output semantic for fragment shader is SV_Target*" );
+ }
+ }
+ }
+ GlobalVariables = GlobalVarsSS.str();
+ Prologue = PrologueSS.str();
+ Epilogue = EpilogueSS.str();
+}
+
+
+void HLSL2GLSLConverter::ProcessVertexShaderArguments( std::vector<ShaderParameterInfo>& Params,
+ String &GlobalVariables,
+ String &Epilogue,
+ String &Prologue )
+{
+ stringstream GlobalVarsSS, PrologueSS, EpilogueSS;
+ GlobalVarsSS <<
+ "\n"
+ "#ifndef GL_ES\n"
+ "out gl_PerVertex\n"
+ "{\n"
+ " vec4 gl_Position;\n"
+ "};\n"
+ "#endif\n";
+ int InterfaceBlockNum = 0;
+ for( const auto &Param : Params )
+ {
+ const auto& Semantic = Param.Semantic;
+ if( Param.storageQualifier == ShaderParameterInfo::StorageQualifier::In )
+ {
+ auto SemanticEndPos = Semantic.begin();
+ if( SkipPrefix( "attrib", SemanticEndPos, Semantic.end() ) )
+ {
+ char* EndPtr = nullptr;
+ auto InputLocation = strtol(&*SemanticEndPos, &EndPtr, 10);
+ if( EndPtr == nullptr || *EndPtr != 0 )
+ {
+ LOG_ERROR_AND_THROW( "Unexpected input semantic \"", Semantic, "\". The only allowed semantic for the vertex shader input attributes is ATTRIB*" );
+ }
+
+ String GlobalVarName = "_in_";
+ GlobalVarName.append( Param.Name );
+ GlobalVarsSS << "layout(location = " << InputLocation << ") in "
+ << Param.Type << ' ' << GlobalVarName << ";\n";
+
+ DeclareVariable( Param.Type.c_str(), Param.Name.c_str(), GlobalVarName.c_str(), false, PrologueSS );
+ }
+ else if( Semantic == "sv_vertexid" )
+ {
+ DeclareVariable( Param.Type.c_str(), Param.Name.c_str(), "gl_VertexID", true, PrologueSS );
+ }
+ else if( Semantic == "sv_instanceid" )
+ {
+ DeclareVariable( Param.Type.c_str(), Param.Name.c_str(), "gl_InstanceID", true, PrologueSS );
+ }
+ else
+ {
+ LOG_ERROR_AND_THROW( "Unexpected input semantic \"", Semantic, "\". The only allowed semantics for the vertex shader inputs are \"ATTRIB*\", \"SV_VertexID\", and \"SV_InstanceID\"." );
+ }
+ }
+ else if( Param.storageQualifier == ShaderParameterInfo::StorageQualifier::Out )
+ {
+ if( Semantic == "" )
+ {
+ // Should be struct
+ DeclareInterfaceBlock( "out", InterfaceBlockNum, Param.Type, Param.Name, GlobalVarsSS );
+ ++InterfaceBlockNum;
+ }
+ else if( Semantic == "sv_position" )
+ {
+ DeclareVariable( Param.Type.c_str(), Param.Name.c_str(), nullptr, false, PrologueSS );
+ EpilogueSS << "gl_Position = " << Param.Name << ";\n" ;
+ }
+ else
+ {
+ LOG_ERROR_AND_THROW( "Unexpected output semantic \"", Semantic, "\". The only allowed semantic for the vertex shader output is \"SV_Position\"." );
+ }
+ }
+ }
+ GlobalVariables = GlobalVarsSS.str();
+ Prologue = PrologueSS.str();
+ Epilogue = EpilogueSS.str();
+}
+
+
+void HLSL2GLSLConverter::ProcessComputeShaderArguments( TokenListType::iterator &TypeToken,
+ std::vector<ShaderParameterInfo>& Params,
+ String &GlobalVariables,
+ String &Prologue )
+{
+ stringstream GlobalVarsSS, PrologueSS;
+
+ auto Token = TypeToken;
+ //[numthreads(16,16,1)]
+ //void TestCS(uint3 DTid : SV_DispatchThreadID)
+ //^
+ --Token;
+ //[numthreads(16,16,1)]
+ // ^
+ //void TestCS(uint3 DTid : SV_DispatchThreadID)
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.begin() && Token->Type == TokenType::ClosingStaple, "Missing numthreads declaration");
+
+ while( Token != m_Tokens.begin() && Token->Type != TokenType::OpenStaple )
+ --Token;
+ //[numthreads(16,16,1)]
+ //^
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.begin(), "Missing numthreads() declaration");
+ auto OpenStapleToken = Token;
+
+ ++Token;
+ //[numthreads(16,16,1)]
+ // ^
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end() && Token->Type == TokenType::Identifier && Token->Literal == "numthreads",
+ "Missing numthreads() declaration" );
+
+ ++Token;
+ //[numthreads(16,16,1)]
+ // ^
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end() && Token->Type == TokenType::OpenBracket,
+ "Missing \'(\' after numthreads" );
+
+ String CSGroupSize[3] = {};
+ static const Char *DirNames[] = { "X", "Y", "Z" };
+ for( int i = 0; i < 3; ++i )
+ {
+ ++Token;
+ //[numthreads(16,16,1)]
+ // ^
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end() && (Token->Type == TokenType::NumericConstant || Token->Type == TokenType::Identifier),
+ "Missing group size for ", DirNames[i], " direction" );
+ CSGroupSize[i] = Token->Literal.c_str();
+ ++Token;
+ //[numthreads(16,16,1)]
+ // ^ ^
+ const Char* ExpectedLiteral = (i < 2) ? "," : ")";
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end() && Token->Literal == ExpectedLiteral,
+ "Missing \'", ExpectedLiteral, "\' after ", DirNames[i], " direction" );
+ }
+
+ //OpenStapleToken
+ //V
+ //[numthreads(16,16,1)]
+ //void TestCS(uint3 DTid : SV_DispatchThreadID)
+ //^
+ //TypeToken
+ TypeToken->Delimiter = OpenStapleToken->Delimiter;
+ m_Tokens.erase( OpenStapleToken, TypeToken );
+ //
+ // void TestCS(uint3 DTid : SV_DispatchThreadID)
+
+ GlobalVarsSS << "layout ( local_size_x = " << CSGroupSize[0]
+ << ", local_size_y = " << CSGroupSize[1] << ", local_size_z = " << CSGroupSize[2] << " ) in;\n";
+
+ for( const auto &Param : Params )
+ {
+ const auto& Semantic = Param.Semantic;
+ if( Param.storageQualifier == ShaderParameterInfo::StorageQualifier::In )
+ {
+ auto SemanticEndPos = Semantic.begin();
+ if( Semantic == "sv_dispatchthreadid" )
+ {
+ DeclareVariable( Param.Type.c_str(), Param.Name.c_str(), "gl_GlobalInvocationID", true, PrologueSS );
+ }
+ else if( Semantic == "sv_groupid" )
+ {
+ DeclareVariable( Param.Type.c_str(), Param.Name.c_str(), "gl_WorkGroupID", true, PrologueSS );
+ }
+ else if( Semantic == "sv_groupthreadid" )
+ {
+ DeclareVariable( Param.Type.c_str(), Param.Name.c_str(), "gl_LocalInvocationID", true, PrologueSS );
+ }
+ else if( Semantic == "sv_groupindex" )
+ {
+ DeclareVariable( Param.Type.c_str(), Param.Name.c_str(), "gl_LocalInvocationIndex", true, PrologueSS );
+ }
+ else
+ {
+ LOG_ERROR_AND_THROW( "Unexpected input semantic \"", Semantic, "\". The only allowed semantics for the vertex shader inputs are \"ATTRIB*\", \"SV_VertexID\", and \"SV_InstanceID\"." );
+ }
+ }
+ else if( Param.storageQualifier == ShaderParameterInfo::StorageQualifier::Out )
+ {
+ LOG_ERROR_AND_THROW( "Output variables are not allowed in compute shaders" );
+ }
+ }
+
+ GlobalVariables = GlobalVarsSS.str();
+ Prologue = PrologueSS.str();
+}
+
+void HLSL2GLSLConverter::ProcessReturnStatements( TokenListType::iterator &Token, const String &Epilogue, const char *EntryPoint )
+{
+ VERIFY_EXPR( Token->Type == TokenType::OpenBrace );
+
+ ++Token; // Skip open brace
+ int BraceCount = 1;
+ // Find matching closing brace
+ while( Token != m_Tokens.end() )
+ {
+ if( Token->Type == TokenType::OpenBrace )
+ ++BraceCount;
+ else if( Token->Type == TokenType::ClosingBrace )
+ {
+ --BraceCount;
+ if( BraceCount == 0 )
+ break;
+ }
+ else if( Token->Type == TokenType::FlowControl )
+ {
+ if( Token->Literal == "return" )
+ {
+ //if( x < 0.5 ) return;
+ // ^
+ m_Tokens.insert( Token, TokenInfo(TokenType::OpenBrace, "{", "\r\n"));
+ Token->Delimiter = "";
+ //if( x < 0.5 )
+ //{return;
+ // ^
+
+ m_Tokens.insert(Token, TokenInfo(TokenType::TextBlock, Epilogue.c_str(), "\r\n"));
+ //if( x < 0.5 )
+ //{
+ //gl_Position = f4PosWS;
+ //return;
+ //^
+
+ while( Token->Type != TokenType::Semicolon )
+ ++Token;
+ //if( x < 0.5 )
+ //{
+ //gl_Position = f4PosWS;
+ //return;
+ // ^
+
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "Unexpected end of file while looking for the \';\'" );
+ ++Token;
+ //if( x < 0.5 )
+ //{
+ //gl_Position = f4PosWS;
+ //return;
+ //float a;
+ //^
+
+ m_Tokens.insert( Token, TokenInfo(TokenType::ClosingBrace, "}", "\r\n") );
+ //if( x < 0.5 )
+ //{
+ //gl_Position = f4PosWS;
+ //return;
+ //}
+ //int a;
+ //^
+
+ continue;
+ }
+ }
+ ++Token;
+ }
+ VERIFY_PARSER_STATE( Token, BraceCount == 0, "No matching closing bracket found" );
+
+ // void main ()
+ // {
+ // ...
+ // }
+ // ^
+ VERIFY_PARSER_STATE(Token, Token != m_Tokens.end(), "Unexpected end of file while looking for the end of body of shader entry point \"", EntryPoint, "\"." );
+ VERIFY_EXPR( Token->Type == TokenType::ClosingBrace );
+ // Insert epilogue before the closing brace
+ m_Tokens.insert(Token, TokenInfo(TokenType::TextBlock, Epilogue.c_str(), Token->Delimiter.c_str()));
+ Token->Delimiter = "\n";
+}
+
+void HLSL2GLSLConverter::ProcessShaderDeclaration( const Char* EntryPoint, SHADER_TYPE ShaderType )
+{
+ auto EntryPointToken = m_Tokens.begin();
+ int NumOpenBraces = 0;
+ while( EntryPointToken != m_Tokens.end() )
+ {
+ if( EntryPointToken->Type == TokenType::OpenBrace )
+ ++NumOpenBraces;
+ else if( EntryPointToken->Type == TokenType::ClosingBrace )
+ {
+ --NumOpenBraces;
+ VERIFY_PARSER_STATE( EntryPointToken, NumOpenBraces >= 0, "Unexpected \'}\'");
+ }
+
+ // Search global scope only
+ if( NumOpenBraces == 0 &&
+ EntryPointToken->Type == TokenType::Identifier &&
+ EntryPointToken->Literal == EntryPoint )
+ break;
+ ++EntryPointToken;
+ }
+ VERIFY_PARSER_STATE( EntryPointToken, EntryPointToken != m_Tokens.end(), "Unable to find shader entry point \"", EntryPoint,'\"' );
+ // void TestPS ( in VSOutput In,
+ // ^
+ // EntryPointToken
+ auto TypeToken = EntryPointToken;
+ --TypeToken;
+ // void TestPS ( in VSOutput In,
+ // ^
+ // TypeToken
+ VERIFY_PARSER_STATE( TypeToken, TypeToken != m_Tokens.begin(), "Missing return type for shader entry point \"", EntryPoint,'\"' );
+ VERIFY_PARSER_STATE( TypeToken, TypeToken->Literal == "void", "Unexpected return type \"", TypeToken->Literal, "\" for shader entry point \"", EntryPoint, "\"\n"
+ "Shader outputs should be declared as out parameters to the function.");
+
+ auto ArgsListStartToken = EntryPointToken;
+ ++ArgsListStartToken;
+ // void TestPS ( in VSOutput In,
+ // ^
+ // ArgsListStartToken
+ VERIFY_PARSER_STATE( ArgsListStartToken, ArgsListStartToken->Type == TokenType::OpenBracket, "Missing argument list for shader entry point \"", EntryPoint,'\"' );
+
+ std::vector<ShaderParameterInfo> ShaderParams;
+ auto ArgsListEndToken = ArgsListStartToken;
+ ParseShaderParameters( ArgsListEndToken, ShaderParams );
+
+ ++ArgsListStartToken;
+ // ArgsListStartToken
+ // V
+ //void TestPS ( in VSOutput In,
+ // out float4 Color : SV_Target,
+ // out float3 Color2 : SV_Target2 )
+ // ^
+ // ArgsListEndToken
+
+ m_Tokens.erase(ArgsListStartToken, ArgsListEndToken);
+ //void TestPS ()
+ EntryPointToken->Literal = "main";
+ //void main ()
+
+ String GlobalVariables, Epilogue, Prologue;
+ try
+ {
+ if( ShaderType == SHADER_TYPE_PIXEL )
+ {
+ ProcessFragmentShaderArguments( ShaderParams, GlobalVariables, Epilogue, Prologue );
+ }
+ else if( ShaderType == SHADER_TYPE_VERTEX )
+ {
+ ProcessVertexShaderArguments( ShaderParams, GlobalVariables, Epilogue, Prologue );
+ }
+ else if( ShaderType == SHADER_TYPE_COMPUTE )
+ {
+ ProcessComputeShaderArguments( TypeToken, ShaderParams, GlobalVariables, Prologue );
+ }
+ }
+ catch( const std::runtime_error & )
+ {
+ LOG_ERROR_AND_THROW( "Failed to process shader parameters for shader \"", EntryPoint, "\"." );
+ }
+
+
+ // void main ()
+ // ^
+ // TypeToken
+
+ // Insert global variables before the function
+ m_Tokens.insert(TypeToken, TokenInfo(TokenType::TextBlock, GlobalVariables.c_str(), TypeToken->Delimiter.c_str()));
+ TypeToken->Delimiter = "\n";
+ auto BodyStartToken = ArgsListEndToken;
+ while( BodyStartToken != m_Tokens.end() && BodyStartToken->Type != TokenType::OpenBrace )
+ ++BodyStartToken;
+ // void main ()
+ // {
+ // ^
+ VERIFY_PARSER_STATE(BodyStartToken, BodyStartToken != m_Tokens.end(), "Unexpected end of file while looking for the body of shader entry point \"", EntryPoint, "\"." );
+ auto FirstStatementToken = BodyStartToken;
+ ++FirstStatementToken;
+ // void main ()
+ // {
+ // int a;
+ // ^
+ VERIFY_PARSER_STATE(FirstStatementToken, FirstStatementToken != m_Tokens.end(), "Unexpected end of file while looking for the body of shader entry point \"", EntryPoint, "\"." );
+
+ // Insert prologue before the first token
+ m_Tokens.insert(FirstStatementToken, TokenInfo(TokenType::TextBlock, Prologue.c_str(), "\n"));
+
+ if( Epilogue.length() > 0 )
+ {
+ auto BodyEndToken = BodyStartToken;
+ ProcessReturnStatements( BodyEndToken, Epilogue, EntryPoint );
+ }
+}
+
+
+void HLSL2GLSLConverter::RemoveSemanticsFromBlock(TokenListType::iterator &Token, TokenType OpenBracketType, TokenType ClosingBracketType, bool IsStruct)
+{
+ VERIFY_EXPR( Token->Type == OpenBracketType );
+
+ int NumOpenBrackets = 0;
+ while( Token != m_Tokens.end() )
+ {
+ if( Token->Type == OpenBracketType )
+ ++NumOpenBrackets;
+ else if( Token->Type == ClosingBracketType )
+ --NumOpenBrackets;
+
+ if( Token->Literal == ":" )
+ {
+ // float4 Pos : POSITION;
+ // ^
+ auto ColonToken = Token;
+ ++Token;
+ // float4 Pos : POSITION;
+ // ^
+ if( Token->Type == TokenType::Identifier )
+ {
+ auto SemanticToken = Token;
+ ++Token;
+ // float4 Pos : POSITION;
+ // ^
+
+ // float4 Pos : POSITION, Normal : NORMAL;
+ // ^
+
+ // float4 Pos : POSITION)
+ // ^
+ if( Token->Type == TokenType::Semicolon || Token->Literal == "," || Token->Type == TokenType::ClosingBracket )
+ {
+ if( IsStruct )
+ {
+ auto TmpIt = SemanticToken->Literal.begin();
+ auto IsSVSemantic = SkipPrefix( "SV_", TmpIt, SemanticToken->Literal.end() );
+ VERIFY_PARSER_STATE(SemanticToken, !IsSVSemantic, "System-value semantics are not allowed in structures. Please make this explicit input/output to the shader")
+ }
+ m_Tokens.erase( ColonToken, Token );
+ // float4 Pos ;
+ // ^
+ }
+ }
+ }
+ else
+ ++Token;
+
+ if( NumOpenBrackets == 0 )
+ break;
+ }
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "Unexpected EOF while parsing body of the structure" );
+}
+
+void HLSL2GLSLConverter::RemoveSemantics()
+{
+ auto Token = m_Tokens.begin();
+ int NumOpenBraces = 0;
+ while( Token != m_Tokens.end() )
+ {
+ if( Token->Type == TokenType::OpenBrace )
+ ++NumOpenBraces;
+ else if( Token->Type == TokenType::ClosingBrace )
+ --NumOpenBraces;
+
+ // Search global scope only
+ if( NumOpenBraces == 0 )
+ {
+ if( Token->Type == TokenType::_struct )
+ {
+ //struct MyStruct
+ //^
+ while( Token != m_Tokens.end() && Token->Type != TokenType::OpenBrace )
+ ++Token;
+
+ VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "Unexpected EOF while searching for the structure body" );
+ //struct MyStruct
+ //{
+ //^
+ RemoveSemanticsFromBlock( Token, TokenType::OpenBrace, TokenType::ClosingBrace, true );
+
+ // struct MyStruct
+ // {
+ // ...
+ // };
+ // ^
+ continue;
+ }
+ else if( Token->Type == TokenType::Identifier )
+ {
+ // Searh for "Identifier(" pattern
+ // In global scope this should be texture declaration
+ // It can also be other things like macro. But this is not a problem.
+ ++Token;
+ if( Token == m_Tokens.end() )
+ break;
+ if( Token->Type == TokenType::OpenBracket )
+ {
+ RemoveSemanticsFromBlock( Token, TokenType::OpenBracket, TokenType::ClosingBracket, false );
+ // void TestVS( ... )
+ // {
+ // ^
+ }
+
+ continue;
+ }
+ }
+
+ ++Token;
+ }
+}
+
+// Remove special shader attributes such as [numthreads(16, 16, 1)]
+void HLSL2GLSLConverter::RemoveSpecialShaderAttributes()
+{
+ auto Token = m_Tokens.begin();
+ int NumOpenBraces = 0;
+ while( Token != m_Tokens.end() )
+ {
+ if( Token->Type == TokenType::OpenBrace )
+ ++NumOpenBraces;
+ else if( Token->Type == TokenType::ClosingBrace )
+ --NumOpenBraces;
+
+ // Search global scope only
+ if( NumOpenBraces == 0 )
+ {
+ if( Token->Type == TokenType::OpenStaple )
+ {
+ auto OpenStaple = Token;
+ ++Token;
+ if( Token == m_Tokens.end() )
+ break;
+ if( Token->Literal == "numthreads" )
+ {
+ ++Token;
+ if( Token->Type != TokenType::OpenBracket )
+ continue;
+ while( Token != m_Tokens.end() && Token->Type != TokenType::ClosingStaple )
+ ++Token;
+ if( Token != m_Tokens.end() )
+ {
+ ++Token;
+ if( Token != m_Tokens.end() )
+ Token->Delimiter = OpenStaple->Delimiter + Token->Delimiter;
+ m_Tokens.erase( OpenStaple, Token );
+ continue;
+ }
+ }
+ }
+ }
+ ++Token;
+ }
+}
+
+String HLSL2GLSLConverter::BuildGLSLSource()
+{
+ String Output;
+ for( const auto& Token : m_Tokens )
+ {
+ Output.append( Token.Delimiter );
+ Output.append( Token.Literal );
+ }
+ return Output;
+}
+
+void HLSL2GLSLConverter::ProcessScope( const TokenListType::iterator &ScopeStart,
+ const TokenListType::iterator &ScopeEnd )
+{
+ VERIFY_EXPR( ScopeStart->Type == TokenType::OpenBrace && ScopeEnd->Type == TokenType::ClosingBrace );
+
+ ProcessObjectMethods(ScopeStart, ScopeEnd);
+
+ ProcessRWTextures(ScopeStart, ScopeEnd);
+
+ ProcessAtomics(ScopeStart, ScopeEnd);
+}
+
+String HLSL2GLSLConverter::Convert( const Char* HLSLSource, size_t NumSymbols, const Char* EntryPoint, SHADER_TYPE ShaderType )
+{
+ String GLSLSource(HLSLSource, NumSymbols);
+
+ InsertIncludes( GLSLSource );
+
+ Tokenize(GLSLSource);
+
+ std::unordered_map<String, bool> SamplersHash;
+ auto Token = m_Tokens.begin();
+ // Process constant buffers, fix floating point constants and
+ // remove flow control attributes
+ while( Token != m_Tokens.end() )
+ {
+ switch( Token->Type )
+ {
+ case TokenType::cbuffer:
+ ProcessConstantBuffer( Token );
+ break;
+
+ case TokenType::NumericConstant:
+ // This all work is only required because some GLSL compilers are so stupid that
+ // flood shader output with insane warnings like this:
+ // WARNING: 0:259: Only GLSL version > 110 allows postfix "F" or "f" for float
+ // even when compiling for GL 4.3 AND the code IS UNDER #if 0
+ if( Token->Literal.back() == 'f' || Token->Literal.back() == 'F' )
+ Token->Literal.pop_back();
+ ++Token;
+ break;
+
+ case TokenType::FlowControl:
+ // Remove flow control attributes like [flatten], [branch], [loop], etc.
+ RemoveFlowControlAttribute( Token );
+ ++Token;
+ break;
+
+ default:
+ ++Token;
+ }
+ }
+
+ // Process textures. GLSL does not allow local variables
+ // of sampler type, so the only two scopes where textures can
+ // be declared are global scope and a function argument list.
+ {
+ TokenListType::iterator FunctionStart = m_Tokens.end();
+ std::vector< SamplerHashType > Samplers;
+
+ // Find all samplers in the global scope
+ Samplers.emplace_back( SamplerHashType() );
+ m_Objects.emplace_back( ObjectsTypeHashType() );
+ Token = m_Tokens.begin();
+ ParseSamplers( Token, Samplers.back() );
+ VERIFY_EXPR( Token == m_Tokens.end() );
+
+ Int32 ScopeDepth = 0;
+
+ Token = m_Tokens.begin();
+ while( Token != m_Tokens.end() )
+ {
+ // Detect global function declaration by looking for the pattern
+ // <return type> Identifier (
+ // in global scope
+ if( ScopeDepth == 0 && Token->Type == TokenType::Identifier )
+ {
+ // float4 Func ( in float2 f2UV,
+ // ^
+ // Token
+ auto ReturnTypeToken = Token;
+ --ReturnTypeToken;
+ ++Token;
+ if( Token == m_Tokens.end() )
+ break;
+ // ReturnTypeToken
+ // |
+ // float4 Func ( in float2 f2UV,
+ // ^
+ // Token
+ if( (ReturnTypeToken->Type == TokenType::BuiltInType ||
+ ReturnTypeToken->Type == TokenType::Identifier ) &&
+ Token->Type == TokenType::OpenBracket )
+ {
+ // Parse samplers in the function argument list
+ Samplers.emplace_back( SamplerHashType() );
+ // GLSL does not support sampler variables,
+ // so the only place where a new sampler
+ // declaration is allowed is function argument
+ // list
+ auto ArgListEnd = Token;
+ ParseSamplers( ArgListEnd, Samplers.back() );
+ // float4 Func ( in float2 f2UV )
+ // ^
+ // ArgListEnd
+ auto OpenBrace = ArgListEnd;
+ ++OpenBrace;
+ // float4 Func ( in float2 f2UV )
+ // {
+ // ^
+ if( OpenBrace->Type == TokenType::OpenBrace )
+ {
+ // We need to go through the function argument
+ // list as there may be texture declaraions
+ ++Token;
+ // float4 Func ( in float2 f2UV,
+ // ^
+ // Token
+
+ // Put empty table on top of the object stack
+ m_Objects.emplace_back( ObjectsTypeHashType() );
+ }
+ else
+ {
+ // For some reason there is no open brace after
+ // what should be argument list - pop the samplers
+ Samplers.pop_back();
+ }
+ }
+ }
+
+ if( Token->Type == TokenType::OpenBrace )
+ {
+ if( Samplers.size() == 2 && ScopeDepth == 0 )
+ {
+ VERIFY_EXPR( FunctionStart == m_Tokens.end() );
+ // This is the first open brace after the
+ // Samplers stack has grown to two -> this is
+ // the beginning of a function body
+ FunctionStart = Token;
+ }
+ ++ScopeDepth;
+ ++Token;
+ }
+ else if( Token->Type == TokenType::ClosingBrace )
+ {
+ --ScopeDepth;
+ if( Samplers.size() == 2 && ScopeDepth == 0 )
+ {
+ // We are returning to the global scope now and
+ // the samplers stack size is 2 -> this was a function
+ // body. We need to process it now.
+ ProcessScope( FunctionStart, Token );
+ // Pop function arguments from the sampler and object
+ // stacks
+ Samplers.pop_back();
+ m_Objects.pop_back();
+ FunctionStart = m_Tokens.end();
+ }
+ ++Token;
+ }
+ else if( Token->Type == TokenType::Texture1D ||
+ Token->Type == TokenType::Texture1DArray ||
+ Token->Type == TokenType::Texture2D ||
+ Token->Type == TokenType::Texture2DArray ||
+ Token->Type == TokenType::Texture3D ||
+ Token->Type == TokenType::TextureCube ||
+ Token->Type == TokenType::TextureCubeArray ||
+ Token->Type == TokenType::Texture2DMS ||
+ Token->Type == TokenType::Texture2DMSArray ||
+ Token->Type == TokenType::RWTexture1D ||
+ Token->Type == TokenType::RWTexture1DArray ||
+ Token->Type == TokenType::RWTexture2D ||
+ Token->Type == TokenType::RWTexture2DArray ||
+ Token->Type == TokenType::RWTexture3D )
+ {
+ // Process texture declaration, and add it to the top of the
+ // object stack
+ ProcessTextureDeclaration( Token, Samplers, m_Objects.back() );
+ }
+ else
+ ++Token;
+ }
+ }
+
+ ProcessShaderDeclaration( EntryPoint, ShaderType );
+
+ RemoveSemantics();
+
+ RemoveSpecialShaderAttributes();
+
+ GLSLSource = BuildGLSLSource();
+
+ return GLSLSource;
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/ProgramPipelineCache.cpp b/Graphics/GraphicsEngineOpenGL/src/ProgramPipelineCache.cpp
new file mode 100644
index 00000000..4d5b3902
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/ProgramPipelineCache.cpp
@@ -0,0 +1,164 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "ProgramPipelineCache.h"
+#include "ShaderGLImpl.h"
+#include "RenderDeviceGLImpl.h"
+
+namespace Diligent
+{
+
+ProgramPipelineCache::ProgramPipelineCache( RenderDeviceGLImpl *pRenderDeviceOpenGL )
+{
+ auto &DeviceCaps = pRenderDeviceOpenGL->GetDeviceCaps();
+ VERIFY( DeviceCaps.DevType != DeviceType::Undefined, "Device caps are not initialized" );
+ m_bIsProgramPipelineSupported = DeviceCaps.bSeparableProgramSupported;
+
+ m_Cache.max_load_factor(0.5f);
+ m_ShaderToKey.max_load_factor(0.5f);
+}
+
+ProgramPipelineCache::~ProgramPipelineCache()
+{
+ VERIFY( m_Cache.empty(), "Program pipeline cache is not empty" );
+ VERIFY( m_ShaderToKey.empty(), "Not all shaders that use the program pipleine are released" );
+}
+
+ProgramPipelineCache::CacheElementType &ProgramPipelineCache::GetProgramPipeline( RefCntAutoPtr<IShader> *ppShaders, Uint32 NumShadersToSet )
+{
+ ThreadingTools::LockHelper LockHelper(m_CacheLockFlag);
+
+ PipelineCacheKey Key = {0};
+ // Create a key for the look-up
+ for(Uint32 Shader = 0; Shader < NumShadersToSet; ++Shader)
+ {
+ auto *pCurrShader = static_cast<IShader*>(ppShaders[Shader].RawPtr());
+ switch(pCurrShader->GetDesc().ShaderType)
+ {
+ case SHADER_TYPE_VERTEX: Key.pVS = pCurrShader; break;
+ case SHADER_TYPE_PIXEL: Key.pPS = pCurrShader; break;
+ case SHADER_TYPE_GEOMETRY:Key.pGS = pCurrShader; break;
+ case SHADER_TYPE_HULL: Key.pHS = pCurrShader; break;
+ case SHADER_TYPE_DOMAIN: Key.pDS = pCurrShader; break;
+ case SHADER_TYPE_COMPUTE: Key.pCS = pCurrShader; break;
+ default: UNEXPECTED( "Unknown shader type" );
+ }
+ }
+
+ // Try to find the Pipeline in the map
+ auto It = m_Cache.find(Key);
+ if( It != m_Cache.end() )
+ {
+ return It->second;
+ }
+ else
+ {
+ CacheElementType NewPipelineOrProg;
+
+ if( m_bIsProgramPipelineSupported )
+ {
+ // Create new progam pipeline
+ NewPipelineOrProg.Pipeline.Create();
+ for( Uint32 Shader = 0; Shader < NumShadersToSet; ++Shader )
+ {
+ auto *pCurrShader = static_cast<ShaderGLImpl*>(ppShaders[Shader].RawPtr());
+ auto GLShaderBit = ShaderTypeToGLShaderBit( pCurrShader->GetDesc().ShaderType );
+ // If the program has an active code for each stage mentioned in set flags,
+ // then that code will be used by the pipeline. If program is 0, then the given
+ // stages are cleared from the pipeline.
+ glUseProgramStages( NewPipelineOrProg.Pipeline, GLShaderBit, pCurrShader->m_GlProgObj );
+ CHECK_GL_ERROR( "glUseProgramStages() failed" );
+ }
+ }
+ else
+ {
+ // Create new progam
+ NewPipelineOrProg.Program.Create();
+ GLuint GLProgram = NewPipelineOrProg.Program;
+ for( Uint32 Shader = 0; Shader < NumShadersToSet; ++Shader )
+ {
+ auto *pCurrShader = static_cast<ShaderGLImpl*>(ppShaders[Shader].RawPtr());
+ glAttachShader( GLProgram, pCurrShader->m_GLShaderObj );
+ CHECK_GL_ERROR( "glAttachShader() failed" );
+ }
+ glLinkProgram( GLProgram );
+ CHECK_GL_ERROR( "glLinkProgram() failed" );
+ int IsLinked = GL_FALSE;
+ glGetProgramiv( GLProgram, GL_LINK_STATUS, (int *)&IsLinked );
+ CHECK_GL_ERROR( "glGetProgramiv() failed" );
+ if( !IsLinked )
+ {
+ int LengthWithNull = 0, Length = 0;
+ // Notice that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv.
+ // The length of the info log includes a null terminator.
+ glGetProgramiv( GLProgram, GL_INFO_LOG_LENGTH, &LengthWithNull );
+
+ // The maxLength includes the NULL character
+ std::vector<char> shaderProgramInfoLog( LengthWithNull );
+
+ // Notice that glGetProgramInfoLog is used, not glGetShaderInfoLog.
+ glGetProgramInfoLog( GLProgram, LengthWithNull, &Length, &shaderProgramInfoLog[0] );
+ VERIFY( Length == LengthWithNull-1, "Incorrect program info log len" );
+ LOG_ERROR_MESSAGE( "Failed to link shader program:\n", &shaderProgramInfoLog[0], '\n');
+ UNEXPECTED( "glLinkProgram failed" );
+ }
+
+ // Detach shaders from the program object
+ for( Uint32 Shader = 0; Shader < NumShadersToSet; ++Shader )
+ {
+ auto *pCurrShader = static_cast<ShaderGLImpl*>(ppShaders[Shader].RawPtr());
+ glDetachShader( GLProgram, pCurrShader->m_GLShaderObj );
+ CHECK_GL_ERROR( "glDetachShader() failed" );
+ }
+
+ NewPipelineOrProg.Program.LoadUniforms();
+ }
+
+ auto NewElems = m_Cache.emplace( make_pair( Key, std::move( NewPipelineOrProg ) ) );
+ // New element must be actually inserted
+ VERIFY( NewElems.second, "Element was not inserted into the hash" );
+ if( Key.pVS )m_ShaderToKey.insert( make_pair(Key.pVS, Key) );
+ if( Key.pGS )m_ShaderToKey.insert( make_pair(Key.pGS, Key) );
+ if( Key.pPS )m_ShaderToKey.insert( make_pair(Key.pPS, Key) );
+ if( Key.pDS )m_ShaderToKey.insert( make_pair(Key.pDS, Key) );
+ if( Key.pHS )m_ShaderToKey.insert( make_pair(Key.pHS, Key) );
+ if( Key.pCS )m_ShaderToKey.insert( make_pair(Key.pCS, Key) );
+
+ return NewElems.first->second;
+ }
+}
+
+void ProgramPipelineCache::OnDestroyShader(IShader *pShader)
+{
+ ThreadingTools::LockHelper LockHelper(m_CacheLockFlag);
+ auto EqualRange = m_ShaderToKey.equal_range(pShader);
+ for(auto It = EqualRange.first; It != EqualRange.second; ++It)
+ {
+ m_Cache.erase(It->second);
+ }
+ m_ShaderToKey.erase(EqualRange.first, EqualRange.second);
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/RasterizerStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RasterizerStateGLImpl.cpp
new file mode 100644
index 00000000..191253f5
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/RasterizerStateGLImpl.cpp
@@ -0,0 +1,43 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "RasterizerStateGLImpl.h"
+#include "RenderDeviceGLImpl.h"
+
+namespace Diligent
+{
+
+RasterizerStateGLImpl::RasterizerStateGLImpl(class IRenderDevice *pDeviceGL, const RasterizerStateDesc& RasterizerStateDesc, bool bIsDeviceInternal) :
+ TRasterizerStateBase(pDeviceGL, RasterizerStateDesc, bIsDeviceInternal)
+{
+}
+
+RasterizerStateGLImpl::~RasterizerStateGLImpl()
+{
+
+}
+
+IMPLEMENT_QUERY_INTERFACE( RasterizerStateGLImpl, IID_RasterizerStateGL, TRasterizerStateBase )
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceFactoryOpenGL.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceFactoryOpenGL.cpp
new file mode 100644
index 00000000..d7efc211
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceFactoryOpenGL.cpp
@@ -0,0 +1,110 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "RenderDeviceFactoryOpenGL.h"
+#include "RenderDeviceGLImpl.h"
+#include "DeviceContextGLImpl.h"
+#include "SwapChainGLImpl.h"
+
+#ifdef PLATFORM_ANDROID
+ #include "RenderDeviceGLESImpl.h"
+#endif
+
+using namespace Diligent;
+using namespace Diligent;
+
+extern "C"
+{
+
+#if defined(PLATFORM_WINDOWS) || defined(PLATFORM_WINDOWS_STORE)
+ typedef RenderDeviceGLImpl TRenderDeviceGLImpl;
+#elif defined(PLATFORM_ANDROID)
+ typedef RenderDeviceGLESImpl TRenderDeviceGLImpl;
+#endif
+
+API_QUALIFIER
+void CreateDeviceAndSwapChainGL( const EngineCreationAttribs& CreationAttribs,
+ IRenderDevice **ppDevice,
+ IDeviceContext **ppImmediateContext,
+ const SwapChainDesc& SwapChainDesc,
+ void *pNativeWndHandle,
+ Diligent::ISwapChain **ppSwapChain )
+{
+ VERIFY( ppDevice && ppImmediateContext && ppSwapChain, "Null pointer is provided" );
+ if( !ppDevice || !ppImmediateContext || !ppSwapChain )
+ return;
+
+ *ppDevice = nullptr;
+ *ppImmediateContext = nullptr;
+ *ppSwapChain = nullptr;
+
+ try
+ {
+ ContextInitInfo InitInfo;
+ InitInfo.pNativeWndHandle = pNativeWndHandle;
+ InitInfo.SwapChainAttribs = SwapChainDesc;
+ RenderDeviceGLImpl *pRenderDeviceOpenGL( new TRenderDeviceGLImpl( InitInfo ) );
+ pRenderDeviceOpenGL->QueryInterface(IID_RenderDevice, reinterpret_cast<IObject**>(ppDevice) );
+
+ DeviceContextGLImpl *pDeviceContextOpenGL( new DeviceContextGLImpl( pRenderDeviceOpenGL ) );
+ // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceOpenGL will
+ // keep a weak reference to the context
+ pDeviceContextOpenGL->QueryInterface(IID_DeviceContext, reinterpret_cast<IObject**>(ppImmediateContext) );
+ pRenderDeviceOpenGL->SetImmediateContext(pDeviceContextOpenGL);
+
+ SwapChainGLImpl *pSwapChainGL = new SwapChainGLImpl(SwapChainDesc, pRenderDeviceOpenGL, pDeviceContextOpenGL );
+ pSwapChainGL->QueryInterface(IID_SwapChain, reinterpret_cast<IObject**>(ppSwapChain) );
+
+ pDeviceContextOpenGL->SetSwapChain(pSwapChainGL);
+ // Bind default framebuffer and viewport
+ pDeviceContextOpenGL->SetRenderTargets( 0, nullptr, nullptr );
+ pDeviceContextOpenGL->SetViewports( 1, nullptr, 0, 0 );
+
+ pDeviceContextOpenGL->CreateDefaultStates();
+ }
+ catch( const std::runtime_error & )
+ {
+ if( *ppDevice )
+ {
+ (*ppDevice)->Release();
+ *ppDevice = nullptr;
+ }
+
+ if( *ppImmediateContext )
+ {
+ (*ppImmediateContext)->Release();
+ *ppImmediateContext = nullptr;
+ }
+
+ if( *ppSwapChain )
+ {
+ (*ppSwapChain)->Release();
+ *ppSwapChain = nullptr;
+ }
+
+ LOG_ERROR( "Failed to initialize OpenGL-based render device" );
+ }
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLESImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLESImpl.cpp
new file mode 100644
index 00000000..932cd4d6
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLESImpl.cpp
@@ -0,0 +1,51 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "RenderDeviceGLESImpl.h"
+
+namespace Diligent
+{
+ RenderDeviceGLESImpl::RenderDeviceGLESImpl( const ContextInitInfo &InitInfo ) :
+ RenderDeviceGLImpl( InitInfo )
+ {
+ }
+
+ IMPLEMENT_QUERY_INTERFACE( RenderDeviceGLESImpl, IID_RenderDeviceGLES, RenderDeviceGLImpl )
+
+ bool RenderDeviceGLESImpl::Invalidate()
+ {
+ return m_GLContext.Invalidate();
+ }
+
+ void RenderDeviceGLESImpl::Suspend()
+ {
+ m_GLContext.Suspend();
+ }
+
+ EGLint RenderDeviceGLESImpl::Resume( ANativeWindow* window )
+ {
+ return m_GLContext.Resume(window);
+ }
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp
new file mode 100644
index 00000000..fafa7f51
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp
@@ -0,0 +1,631 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "RenderDeviceGLImpl.h"
+
+#include "BufferGLImpl.h"
+#include "VertexDescGLImpl.h"
+#include "ShaderGLImpl.h"
+#include "VAOCache.h"
+#include "ProgramPipelineCache.h"
+#include "Texture1D_OGL.h"
+#include "Texture1DArray_OGL.h"
+#include "Texture2D_OGL.h"
+#include "Texture2DArray_OGL.h"
+#include "Texture3D_OGL.h"
+#include "SamplerGLImpl.h"
+#include "DSStateGLImpl.h"
+#include "RasterizerStateGLImpl.h"
+#include "BlendStateGLImpl.h"
+#include "DeviceContextGLImpl.h"
+#include "GLTypeConversions.h"
+
+namespace Diligent
+{
+
+RenderDeviceGLImpl :: RenderDeviceGLImpl(const ContextInitInfo &InitInfo):
+ // Device caps must be filled in before the constructor of Pipeline Cache is called!
+ m_GLContext(InitInfo, m_DeviceCaps),
+ m_PipelineCache(this),
+ m_EmptyVAO(true),
+ m_TexRegionRender(this)
+{
+ GLint NumExtensions = 0;
+ glGetIntegerv( GL_NUM_EXTENSIONS, &NumExtensions );
+ CHECK_GL_ERROR( "Failed to get the number of extensions" );
+ m_ExtensionStrings.reserve(NumExtensions);
+ for( int Ext = 0; Ext < NumExtensions; ++Ext )
+ {
+ auto CurrExtension = glGetStringi( GL_EXTENSIONS, Ext );
+ CHECK_GL_ERROR( "Failed to get extension string #", Ext );
+ m_ExtensionStrings.emplace( reinterpret_cast<const Char*>(CurrExtension) );
+ }
+
+ FlagSupportedTexFormats();
+ QueryDeviceCaps();
+
+ std::basic_string<GLubyte> glstrVendor = glGetString( GL_VENDOR );
+ std::string Vendor(glstrVendor.begin(), glstrVendor.end());
+ transform(Vendor.begin(), Vendor.end(), Vendor.begin(), ::tolower);
+ if( Vendor.find( "intel" ) != string::npos )
+ m_GPUInfo.Vendor = GPU_VENDOR::INTEL;
+ else if( Vendor.find( "nvidia" ) != string::npos )
+ m_GPUInfo.Vendor = GPU_VENDOR::NVIDIA;
+ else if( Vendor.find( "ati" ) != string::npos ||
+ Vendor.find( "amd" ) != string::npos )
+ m_GPUInfo.Vendor = GPU_VENDOR::ATI;
+}
+
+RenderDeviceGLImpl :: ~RenderDeviceGLImpl()
+{
+}
+
+IMPLEMENT_QUERY_INTERFACE( RenderDeviceGLImpl, IID_GLDeviceBaseInterface, TRenderDeviceBase )
+
+void RenderDeviceGLImpl :: CreateBuffer(const BufferDesc& BuffDesc, const BufferData &BuffData, IBuffer **ppBuffer, bool bIsDeviceInternal)
+{
+ CreateDeviceObject( "buffer", BuffDesc, ppBuffer,
+ [&]()
+ {
+ BufferGLImpl *pBufferOGL( new BufferGLImpl( this, BuffDesc, BuffData, bIsDeviceInternal ) );
+ pBufferOGL->QueryInterface( IID_Buffer, reinterpret_cast<IObject**>(ppBuffer) );
+ pBufferOGL->CreateDefaultViews();
+ OnCreateDeviceObject( pBufferOGL );
+ }
+ );
+}
+
+void RenderDeviceGLImpl :: CreateBuffer(const BufferDesc& BuffDesc, const BufferData &BuffData, IBuffer **ppBuffer)
+{
+ CreateBuffer(BuffDesc, BuffData, ppBuffer, false);
+}
+
+void RenderDeviceGLImpl::CreateVertexDescription( const LayoutDesc& LayoutDesc, IShader *pVertexShader, IVertexDescription **ppVertexDesc, bool bIsDeviceInternal )
+{
+ CreateDeviceObject( "vertex description", LayoutDesc, ppVertexDesc,
+ [&]()
+ {
+ VertexDescGLImpl *pDescOGL( new VertexDescGLImpl( this, LayoutDesc, bIsDeviceInternal ) );
+ pDescOGL->QueryInterface(IID_VertexDescription, reinterpret_cast<IObject**>(ppVertexDesc) );
+
+ OnCreateDeviceObject( pDescOGL );
+ }
+ );
+}
+void RenderDeviceGLImpl::CreateVertexDescription(const LayoutDesc& LayoutDesc, IShader *pVertexShader, IVertexDescription **ppVertexDesc)
+{
+ CreateVertexDescription(LayoutDesc, pVertexShader, ppVertexDesc, false);
+}
+
+
+void RenderDeviceGLImpl :: CreateShader(const ShaderCreationAttribs &ShaderCreationAttribs, IShader **ppShader, bool bIsDeviceInternal)
+{
+ CreateDeviceObject( "shader", ShaderCreationAttribs.Desc, ppShader,
+ [&]()
+ {
+ ShaderGLImpl *pShaderOGL(new ShaderGLImpl(this, ShaderCreationAttribs, bIsDeviceInternal));
+ pShaderOGL->QueryInterface(IID_Shader, reinterpret_cast<IObject**>(ppShader) );
+
+ OnCreateDeviceObject( pShaderOGL );
+ }
+ );
+}
+
+void RenderDeviceGLImpl :: CreateShader(const ShaderCreationAttribs &ShaderCreationAttribs, IShader **ppShader)
+{
+ CreateShader(ShaderCreationAttribs, ppShader, false);
+}
+
+void RenderDeviceGLImpl :: CreateTexture(const TextureDesc& TexDesc, const TextureData &Data, ITexture **ppTexture, bool bIsDeviceInternal)
+{
+ CreateDeviceObject( "texture", TexDesc, ppTexture,
+ [&]()
+ {
+ auto spDeviceContext = GetImmediateContext();
+ VERIFY(spDeviceContext, "Immediate device context has been destroyed");
+ auto pDeviceContext = ValidatedCast<DeviceContextGLImpl>( spDeviceContext.RawPtr() );
+ const auto &FmtInfo = GetTextureFormatInfo( TexDesc.Format );
+ if( !FmtInfo.Supported )
+ {
+ LOG_ERROR_AND_THROW( FmtInfo.Name, " is not supported texture format" );
+ }
+
+ TextureBaseGL *pTextureOGL = nullptr;
+ switch(TexDesc.Type)
+ {
+ case TEXTURE_TYPE_1D:
+ pTextureOGL = new Texture1D_OGL(this, pDeviceContext, TexDesc, Data, bIsDeviceInternal);
+ break;
+
+ case TEXTURE_TYPE_1D_ARRAY:
+ pTextureOGL = new Texture1DArray_OGL(this, pDeviceContext, TexDesc, Data, bIsDeviceInternal);
+ break;
+
+ case TEXTURE_TYPE_2D:
+ pTextureOGL = new Texture2D_OGL(this, pDeviceContext, TexDesc, Data, bIsDeviceInternal);
+ break;
+
+ case TEXTURE_TYPE_2D_ARRAY:
+ pTextureOGL = new Texture2DArray_OGL(this, pDeviceContext, TexDesc, Data, bIsDeviceInternal);
+ break;
+
+ case TEXTURE_TYPE_3D:
+ pTextureOGL = new Texture3D_OGL(this, pDeviceContext, TexDesc, Data, bIsDeviceInternal);
+ break;
+
+ default: LOG_ERROR_AND_THROW( "Unknown texture type. (Did you forget to initialize the Type member of TextureDesc structure?)" );
+ }
+
+ pTextureOGL->QueryInterface( IID_Texture, reinterpret_cast<IObject**>(ppTexture) );
+ pTextureOGL->CreateDefaultViews();
+ OnCreateDeviceObject( pTextureOGL );
+ }
+ );
+}
+
+void RenderDeviceGLImpl::CreateTexture(const TextureDesc& TexDesc, const TextureData &Data, ITexture **ppTexture)
+{
+ CreateTexture(TexDesc, Data, ppTexture, false);
+}
+
+void RenderDeviceGLImpl :: CreateSampler(const SamplerDesc& SamplerDesc, ISampler **ppSampler, bool bIsDeviceInternal)
+{
+ CreateDeviceObject( "sampler", SamplerDesc, ppSampler,
+ [&]()
+ {
+ m_SamplersRegistry.Find( SamplerDesc, reinterpret_cast<IDeviceObject**>(ppSampler) );
+ if( *ppSampler == nullptr )
+ {
+ SamplerGLImpl *pSamplerOGL( new SamplerGLImpl( this, SamplerDesc, bIsDeviceInternal ) );
+ pSamplerOGL->QueryInterface( IID_Sampler, reinterpret_cast<IObject**>(ppSampler) );
+ OnCreateDeviceObject( pSamplerOGL );
+ m_SamplersRegistry.Add( SamplerDesc, *ppSampler );
+ }
+ }
+ );
+}
+
+void RenderDeviceGLImpl::CreateSampler(const SamplerDesc& SamplerDesc, ISampler **ppSampler)
+{
+ CreateSampler(SamplerDesc, ppSampler, false);
+}
+
+void RenderDeviceGLImpl::CreateDepthStencilState( const DepthStencilStateDesc &DSSDesc, IDepthStencilState **ppDepthStencilState, bool bIsDeviceInternal )
+{
+ CreateDeviceObject( "depth-stencil state", DSSDesc, ppDepthStencilState,
+ [&]()
+ {
+ m_DSSRegistry.Find( DSSDesc, reinterpret_cast<IDeviceObject**>(ppDepthStencilState) );
+ if( *ppDepthStencilState == nullptr )
+ {
+ DSStateGLImpl *pDSSOGL( new DSStateGLImpl( this, DSSDesc, bIsDeviceInternal ) );
+ pDSSOGL->QueryInterface( IID_DepthStencilState, reinterpret_cast<IObject**>(ppDepthStencilState) );
+ OnCreateDeviceObject( pDSSOGL );
+ m_DSSRegistry.Add( DSSDesc, pDSSOGL );
+ }
+ }
+ );
+}
+
+void RenderDeviceGLImpl::CreateDepthStencilState(const DepthStencilStateDesc &DSSDesc, IDepthStencilState **ppDepthStencilState)
+{
+ CreateDepthStencilState( DSSDesc, ppDepthStencilState, false );
+}
+
+void RenderDeviceGLImpl::CreateRasterizerState( const RasterizerStateDesc &RSDesc, IRasterizerState **ppRasterizerState, bool bIsDeviceInternal )
+{
+ CreateDeviceObject( "rasterizer state", RSDesc, ppRasterizerState,
+ [&]()
+ {
+ m_RSRegistry.Find( RSDesc, reinterpret_cast<IDeviceObject**>(ppRasterizerState) );
+ if( *ppRasterizerState == nullptr )
+ {
+ RasterizerStateGLImpl *pRSOGL( new RasterizerStateGLImpl( this, RSDesc, bIsDeviceInternal ) );
+ pRSOGL->QueryInterface( IID_RasterizerState, reinterpret_cast<IObject**>(ppRasterizerState) );
+ OnCreateDeviceObject( pRSOGL );
+ m_RSRegistry.Add( RSDesc, pRSOGL );
+ }
+ }
+ );
+}
+void RenderDeviceGLImpl::CreateRasterizerState(const RasterizerStateDesc &RSDesc, IRasterizerState **ppRasterizerState)
+{
+ CreateRasterizerState( RSDesc, ppRasterizerState, false );
+}
+
+void RenderDeviceGLImpl::CreateBlendState( const BlendStateDesc &BSDesc, IBlendState **ppBlendState, bool bIsDeviceInternal )
+{
+ CreateDeviceObject( "blend state", BSDesc, ppBlendState,
+ [&]()
+ {
+ m_BSRegistry.Find( BSDesc, reinterpret_cast<IDeviceObject**>(ppBlendState) );
+ if( *ppBlendState == nullptr )
+ {
+ BlendStateGLImpl *pBSOGL( new BlendStateGLImpl( this, BSDesc, bIsDeviceInternal ) );
+ pBSOGL->QueryInterface( IID_BlendState, reinterpret_cast<IObject**>(ppBlendState) );
+ OnCreateDeviceObject( pBSOGL );
+ m_BSRegistry.Add( BSDesc, pBSOGL );
+ }
+ }
+ );
+}
+void RenderDeviceGLImpl::CreateBlendState(const BlendStateDesc &BSDesc, IBlendState **ppBlendState)
+{
+ CreateBlendState( BSDesc, ppBlendState, false );
+}
+
+bool RenderDeviceGLImpl::CheckExtension( const Char *ExtensionString )
+{
+ return m_ExtensionStrings.find( ExtensionString ) != m_ExtensionStrings.end();
+}
+
+void RenderDeviceGLImpl::FlagSupportedTexFormats()
+{
+ const auto &DeviceCaps = GetDeviceCaps();
+ bool bGL33OrAbove = DeviceCaps.DevType == DeviceType::OpenGL &&
+ (DeviceCaps.MajorVersion >= 4 || DeviceCaps.MajorVersion == 3 && DeviceCaps.MinorVersion >= 3);
+
+ bool bRGTC = CheckExtension( "GL_ARB_texture_compression_rgtc" );
+ bool bBPTC = CheckExtension( "GL_ARB_texture_compression_bptc" );
+ bool bS3TC = CheckExtension( "GL_EXT_texture_compression_s3tc" );
+ bool bTexNorm16 = CheckExtension( "GL_EXT_texture_norm16" ); // Only for ES3.1+
+
+#define FLAG_FORMAT(Fmt, IsSupported)\
+ m_TextureFormatsInfo[Fmt].Supported=IsSupported
+
+ // The formats marked by true below are required in GL 3.3+ and GLES 3.0+
+ // Note that GLES2.0 does not specify any required formats
+
+ FLAG_FORMAT(TEX_FORMAT_RGBA32_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_RGBA32_FLOAT, true );
+ FLAG_FORMAT(TEX_FORMAT_RGBA32_UINT, true );
+ FLAG_FORMAT(TEX_FORMAT_RGBA32_SINT, true );
+ FLAG_FORMAT(TEX_FORMAT_RGB32_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_RGB32_FLOAT, true );
+ FLAG_FORMAT(TEX_FORMAT_RGB32_UINT, true );
+ FLAG_FORMAT(TEX_FORMAT_RGB32_SINT, true );
+ FLAG_FORMAT(TEX_FORMAT_RGBA16_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_RGBA16_FLOAT, true );
+ FLAG_FORMAT(TEX_FORMAT_RGBA16_UNORM, bGL33OrAbove || bTexNorm16 );
+ FLAG_FORMAT(TEX_FORMAT_RGBA16_UINT, true );
+ FLAG_FORMAT(TEX_FORMAT_RGBA16_SNORM, bGL33OrAbove || bTexNorm16 );
+ FLAG_FORMAT(TEX_FORMAT_RGBA16_SINT, true );
+ FLAG_FORMAT(TEX_FORMAT_RG32_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_RG32_FLOAT, true );
+ FLAG_FORMAT(TEX_FORMAT_RG32_UINT, true );
+ FLAG_FORMAT(TEX_FORMAT_RG32_SINT, true );
+ FLAG_FORMAT(TEX_FORMAT_R32G8X24_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_D32_FLOAT_S8X24_UINT, true );
+ FLAG_FORMAT(TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_X32_TYPELESS_G8X24_UINT, false );
+ FLAG_FORMAT(TEX_FORMAT_RGB10A2_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_RGB10A2_UNORM, true );
+ FLAG_FORMAT(TEX_FORMAT_RGB10A2_UINT, true );
+ FLAG_FORMAT(TEX_FORMAT_R11G11B10_FLOAT, true );
+ FLAG_FORMAT(TEX_FORMAT_RGBA8_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_RGBA8_UNORM, true );
+ FLAG_FORMAT(TEX_FORMAT_RGBA8_UNORM_SRGB, true );
+ FLAG_FORMAT(TEX_FORMAT_RGBA8_UINT, true );
+ FLAG_FORMAT(TEX_FORMAT_RGBA8_SNORM, true );
+ FLAG_FORMAT(TEX_FORMAT_RGBA8_SINT, true );
+ FLAG_FORMAT(TEX_FORMAT_RG16_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_RG16_FLOAT, true );
+ FLAG_FORMAT(TEX_FORMAT_RG16_UNORM, bGL33OrAbove || bTexNorm16 );
+ FLAG_FORMAT(TEX_FORMAT_RG16_UINT, true );
+ FLAG_FORMAT(TEX_FORMAT_RG16_SNORM, bGL33OrAbove || bTexNorm16 );
+ FLAG_FORMAT(TEX_FORMAT_RG16_SINT, true );
+ FLAG_FORMAT(TEX_FORMAT_R32_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_D32_FLOAT, true );
+ FLAG_FORMAT(TEX_FORMAT_R32_FLOAT, true );
+ FLAG_FORMAT(TEX_FORMAT_R32_UINT, true );
+ FLAG_FORMAT(TEX_FORMAT_R32_SINT, true );
+ FLAG_FORMAT(TEX_FORMAT_R24G8_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_D24_UNORM_S8_UINT, true );
+ FLAG_FORMAT(TEX_FORMAT_R24_UNORM_X8_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_X24_TYPELESS_G8_UINT, false );
+ FLAG_FORMAT(TEX_FORMAT_RG8_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_RG8_UNORM, true );
+ FLAG_FORMAT(TEX_FORMAT_RG8_UINT, true );
+ FLAG_FORMAT(TEX_FORMAT_RG8_SNORM, true );
+ FLAG_FORMAT(TEX_FORMAT_RG8_SINT, true );
+ FLAG_FORMAT(TEX_FORMAT_R16_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_R16_FLOAT, true );
+ FLAG_FORMAT(TEX_FORMAT_D16_UNORM, true );
+ FLAG_FORMAT(TEX_FORMAT_R16_UNORM, bGL33OrAbove || bTexNorm16 );
+ FLAG_FORMAT(TEX_FORMAT_R16_UINT, true );
+ FLAG_FORMAT(TEX_FORMAT_R16_SNORM, bGL33OrAbove || bTexNorm16 );
+ FLAG_FORMAT(TEX_FORMAT_R16_SINT, true );
+ FLAG_FORMAT(TEX_FORMAT_R8_TYPELESS, true );
+ FLAG_FORMAT(TEX_FORMAT_R8_UNORM, true );
+ FLAG_FORMAT(TEX_FORMAT_R8_UINT, true );
+ FLAG_FORMAT(TEX_FORMAT_R8_SNORM, true );
+ FLAG_FORMAT(TEX_FORMAT_R8_SINT, true );
+ FLAG_FORMAT(TEX_FORMAT_A8_UNORM, false ); // Not supported in OpenGL
+ FLAG_FORMAT(TEX_FORMAT_R1_UNORM, false ); // Not supported in OpenGL
+ FLAG_FORMAT(TEX_FORMAT_RGB9E5_SHAREDEXP, true );
+ FLAG_FORMAT(TEX_FORMAT_RG8_B8G8_UNORM, false ); // Not supported in OpenGL
+ FLAG_FORMAT(TEX_FORMAT_G8R8_G8B8_UNORM, false ); // Not supported in OpenGL
+
+ FLAG_FORMAT(TEX_FORMAT_BC1_TYPELESS, bS3TC );
+ FLAG_FORMAT(TEX_FORMAT_BC1_UNORM, bS3TC );
+ FLAG_FORMAT(TEX_FORMAT_BC1_UNORM_SRGB, bS3TC );
+ FLAG_FORMAT(TEX_FORMAT_BC2_TYPELESS, bS3TC );
+ FLAG_FORMAT(TEX_FORMAT_BC2_UNORM, bS3TC );
+ FLAG_FORMAT(TEX_FORMAT_BC2_UNORM_SRGB, bS3TC );
+ FLAG_FORMAT(TEX_FORMAT_BC3_TYPELESS, bS3TC );
+ FLAG_FORMAT(TEX_FORMAT_BC3_UNORM, bS3TC );
+ FLAG_FORMAT(TEX_FORMAT_BC3_UNORM_SRGB, bS3TC );
+
+ FLAG_FORMAT(TEX_FORMAT_BC4_TYPELESS, bRGTC );
+ FLAG_FORMAT(TEX_FORMAT_BC4_UNORM, bRGTC );
+ FLAG_FORMAT(TEX_FORMAT_BC4_SNORM, bRGTC );
+ FLAG_FORMAT(TEX_FORMAT_BC5_TYPELESS, bRGTC );
+ FLAG_FORMAT(TEX_FORMAT_BC5_UNORM, bRGTC );
+ FLAG_FORMAT(TEX_FORMAT_BC5_SNORM, bRGTC );
+
+ FLAG_FORMAT(TEX_FORMAT_B5G6R5_UNORM, false ); // Not supported in OpenGL
+ FLAG_FORMAT(TEX_FORMAT_B5G5R5A1_UNORM, false ); // Not supported in OpenGL
+ FLAG_FORMAT(TEX_FORMAT_BGRA8_UNORM, false ); // Not supported in OpenGL
+ FLAG_FORMAT(TEX_FORMAT_BGRX8_UNORM, false ); // Not supported in OpenGL
+ FLAG_FORMAT(TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, false ); // Not supported in OpenGL
+ FLAG_FORMAT(TEX_FORMAT_BGRA8_TYPELESS, false ); // Not supported in OpenGL
+ FLAG_FORMAT(TEX_FORMAT_BGRA8_UNORM_SRGB, false ); // Not supported in OpenGL
+ FLAG_FORMAT(TEX_FORMAT_BGRX8_TYPELESS, false ); // Not supported in OpenGL
+ FLAG_FORMAT(TEX_FORMAT_BGRX8_UNORM_SRGB, false ); // Not supported in OpenGL
+
+ FLAG_FORMAT(TEX_FORMAT_BC6H_TYPELESS, bBPTC );
+ FLAG_FORMAT(TEX_FORMAT_BC6H_UF16, bBPTC );
+ FLAG_FORMAT(TEX_FORMAT_BC6H_SF16, bBPTC );
+ FLAG_FORMAT(TEX_FORMAT_BC7_TYPELESS, bBPTC );
+ FLAG_FORMAT(TEX_FORMAT_BC7_UNORM, bBPTC );
+ FLAG_FORMAT(TEX_FORMAT_BC7_UNORM_SRGB, bBPTC );
+
+#ifdef _DEBUG
+ bool bGL43OrAbove = DeviceCaps.DevType == DeviceType::OpenGL &&
+ (DeviceCaps.MajorVersion >= 5 || DeviceCaps.MajorVersion == 4 && DeviceCaps.MinorVersion >= 3);
+
+ const int TestTextureDim = 32;
+ const int MaxTexelSize = 16;
+ std::vector<Uint8> ZeroData(TestTextureDim * TestTextureDim * MaxTexelSize);
+
+ // Go through all formats and try to create small 2D texture to check if the format is supported
+ for( auto FmtInfo = m_TextureFormatsInfo.begin(); FmtInfo != m_TextureFormatsInfo.end(); ++FmtInfo )
+ {
+ if( FmtInfo->Format == TEX_FORMAT_UNKNOWN )
+ continue;
+
+ auto GLFmt = TexFormatToGLInternalTexFormat(FmtInfo->Format);
+ if( GLFmt == 0 )
+ {
+ VERIFY( !FmtInfo->Supported, "Format should be marked as unsupported" );
+ continue;
+ }
+
+ // Only works on GL4.3+
+ if( bGL43OrAbove )
+ {
+ GLint params = 0;
+ glGetInternalformativ( GL_TEXTURE_2D, GLFmt, GL_INTERNALFORMAT_SUPPORTED, 1, &params );
+ CHECK_GL_ERROR( "glGetInternalformativ() failed" );
+ VERIFY( FmtInfo->Supported == (params == GL_TRUE), "This internal format should be supported" );
+ }
+
+ // Check that the format is indeed supported
+ if( FmtInfo->Supported )
+ {
+ GLObjectWrappers::GLTextureObj TestGLTex( true );
+ // Immediate context is not created yet, so use raw GL functions
+ glBindTexture( GL_TEXTURE_2D, TestGLTex );
+ CHECK_GL_ERROR( "Failed to bind texture" );
+ glTexStorage2D( GL_TEXTURE_2D, 1, GLFmt, TestTextureDim, TestTextureDim );
+ CHECK_GL_ERROR( "Failed to allocate storage for the test texture. Test format: ", FmtInfo->Name);
+
+ // It turned out it is not enough to only allocate texture storage
+ // For some reason glTexStorage2D() may succeed, but upload operation
+ // will later fail. So we need to additionally try to upload some
+ // data to the texture
+ auto TransferAttribs = GetNativePixelTransferAttribs( FmtInfo->Format );
+ if( FmtInfo->ComponentType != COMPONENT_TYPE_COMPRESSED )
+ {
+ glTexSubImage2D( GL_TEXTURE_2D, 0, // mip level
+ 0, 0, TestTextureDim, TestTextureDim,
+ TransferAttribs.PixelFormat, TransferAttribs.DataType,
+ ZeroData.data() );
+ }
+ CHECK_GL_ERROR( "Failed to upload data to the test texture. Test format: ", FmtInfo->Name);
+ glBindTexture( GL_TEXTURE_2D, 0 );
+ }
+ }
+#endif
+}
+
+template<typename CreateFuncType>
+bool CreateTestGLTexture(GLContextState &GlCtxState, GLenum BindTarget, const GLObjectWrappers::GLTextureObj &GLTexObj, CreateFuncType CreateFunc)
+{
+ GlCtxState.BindTexture(-1, BindTarget, GLTexObj);
+ CreateFunc();
+ bool bSuccess = glGetError() == GL_NO_ERROR;
+ GlCtxState.BindTexture(-1, BindTarget, GLObjectWrappers::GLTextureObj(false) );
+ return bSuccess;
+}
+
+void RenderDeviceGLImpl::TestTextureFormat( TEXTURE_FORMAT TexFormat )
+{
+ auto &TexFormatInfo = m_TextureFormatsInfo[TexFormat];
+ VERIFY( TexFormatInfo.Supported, "Texture format is not supported" );
+
+ auto GLFmt = TexFormatToGLInternalTexFormat(TexFormat);
+ VERIFY( GLFmt != 0, "Incorrect internal GL format" );
+
+ auto spDeviceContext = GetImmediateContext();
+ VERIFY(spDeviceContext, "Immediate device context has been destroyed");
+ auto *pContextGL = ValidatedCast<DeviceContextGLImpl>( spDeviceContext.RawPtr() );
+ auto &ContextState = pContextGL->GetContextState();
+
+ const int TestTextureDim = 32;
+ const int TestTextureDepth = 8;
+
+ // Create test texture 1D
+ TexFormatInfo.Tex1DFmt = false;
+ if( m_DeviceCaps.TexCaps.bTexture1DSupported &&
+ TexFormatInfo.ComponentType != COMPONENT_TYPE_COMPRESSED )
+ {
+ GLObjectWrappers::GLTextureObj TestGLTex( true );
+ TexFormatInfo.Tex1DFmt = CreateTestGLTexture( ContextState, GL_TEXTURE_1D, TestGLTex, [&]()
+ {
+ glTexStorage1D(GL_TEXTURE_1D, 1, GLFmt, TestTextureDim);
+ } );
+ }
+
+ // Create test texture 2D
+ TexFormatInfo.Tex2DFmt = false;
+ TexFormatInfo.TexCubeFmt = false;
+ TexFormatInfo.ColorRenderable = false;
+ TexFormatInfo.DepthRenderable = false;
+ {
+ GLObjectWrappers::GLTextureObj TestGLTex( true );
+ TexFormatInfo.Tex2DFmt = CreateTestGLTexture( ContextState, GL_TEXTURE_2D, TestGLTex, [&]()
+ {
+ glTexStorage2D(GL_TEXTURE_2D, 1, GLFmt, TestTextureDim, TestTextureDim);
+ } );
+
+ if( TexFormatInfo.Tex2DFmt )
+ {
+ {
+ GLObjectWrappers::GLTextureObj TestGLCubeTex( true );
+ TexFormatInfo.TexCubeFmt = CreateTestGLTexture( ContextState, GL_TEXTURE_CUBE_MAP, TestGLCubeTex, [&]()
+ {
+ glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GLFmt, TestTextureDim, TestTextureDim);
+ } );
+ }
+
+ bool bTestDepthAttachment =
+ TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH ||
+ TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL;
+ bool bTestColorAttachment = !bTestDepthAttachment && TexFormatInfo.ComponentType != COMPONENT_TYPE_COMPRESSED;
+
+ GLObjectWrappers::GLFrameBufferObj NewFBO(false);
+
+ GLint CurrentFramebuffer = -1;
+ if( bTestColorAttachment || bTestDepthAttachment )
+ {
+ glGetIntegerv( GL_DRAW_FRAMEBUFFER_BINDING, &CurrentFramebuffer );
+ CHECK_GL_ERROR( "Failed to get current framebuffer");
+
+ NewFBO.Create();
+ glBindFramebuffer( GL_DRAW_FRAMEBUFFER, NewFBO );
+ CHECK_GL_ERROR( "Failed to bind the framebuffer");
+ }
+
+ if( bTestDepthAttachment )
+ {
+ GLenum Attachment = TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH ? GL_DEPTH_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT;
+ glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER, Attachment, GL_TEXTURE_2D, TestGLTex, 0 );
+ if( glGetError() == GL_NO_ERROR )
+ {
+ // Create dummy texture2D since some older version do not allow depth only
+ // attachments
+ GLObjectWrappers::GLTextureObj ColorTex( true );
+ bool Success = CreateTestGLTexture( ContextState, GL_TEXTURE_2D, ColorTex, [&]()
+ {
+ glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, TestTextureDim, TestTextureDim);
+ } );
+ VERIFY( Success, "Failed to create dummy render target texture" );
+ glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ColorTex, 0 );
+ CHECK_GL_ERROR( "Failed to set bind dummy render target to framebuffer" );
+
+ static const GLenum DrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
+ glDrawBuffers( _countof( DrawBuffers ), DrawBuffers );
+ CHECK_GL_ERROR( "Failed to set draw buffers via glDrawBuffers()" );
+
+ GLenum Status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
+ TexFormatInfo.DepthRenderable = (glGetError() == GL_NO_ERROR) && (Status == GL_FRAMEBUFFER_COMPLETE);
+ }
+ }
+ else if( bTestColorAttachment )
+ {
+ glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, TestGLTex, 0 );
+ if( glGetError() == GL_NO_ERROR )
+ {
+ static const GLenum DrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
+ glDrawBuffers( _countof( DrawBuffers ), DrawBuffers );
+ CHECK_GL_ERROR( "Failed to set draw buffers via glDrawBuffers()" );
+
+ GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ TexFormatInfo.ColorRenderable = (glGetError() == GL_NO_ERROR) && (Status == GL_FRAMEBUFFER_COMPLETE);
+ }
+ }
+
+ if( bTestColorAttachment || bTestDepthAttachment )
+ {
+ glBindFramebuffer( GL_DRAW_FRAMEBUFFER, CurrentFramebuffer );
+ CHECK_GL_ERROR( "Failed to bind the framebuffer");
+ }
+ }
+ }
+
+ TexFormatInfo.SupportsMS = false;
+ if( TexFormatInfo.ComponentType != COMPONENT_TYPE_COMPRESSED &&
+ m_DeviceCaps.TexCaps.bTexture2DMSSupported )
+ {
+ GLObjectWrappers::GLTextureObj TestGLTex( true );
+ TexFormatInfo.SupportsMS = CreateTestGLTexture( ContextState, GL_TEXTURE_2D_MULTISAMPLE, TestGLTex, [&]()
+ {
+ glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GLFmt, TestTextureDim, TestTextureDim, GL_TRUE);
+ } );
+ }
+
+ // Create test texture 3D
+ TexFormatInfo.Tex3DFmt = false;
+ // 3D textures do not support depth formats
+ if( !(TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH ||
+ TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL) )
+ {
+ GLObjectWrappers::GLTextureObj TestGLTex( true );
+ TexFormatInfo.Tex3DFmt = CreateTestGLTexture( ContextState, GL_TEXTURE_3D, TestGLTex, [&]()
+ {
+ glTexStorage3D(GL_TEXTURE_3D, 1, GLFmt, TestTextureDim, TestTextureDim, TestTextureDepth);
+ } );
+ }
+}
+
+void RenderDeviceGLImpl :: QueryDeviceCaps()
+{
+ {
+ // Test glPolygonMode() function to check if it fails
+ // (It does fail on NVidia Shield tablet, but works fine
+ // on Intel hw)
+ VERIFY( glGetError() == GL_NO_ERROR, "Unhandled gl error encountered" );
+ m_DeviceCaps.bWireframeFillSupported = True;
+ glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+ if( glGetError() != GL_NO_ERROR )
+ m_DeviceCaps.bWireframeFillSupported = False;
+ glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
+ if( glGetError() != GL_NO_ERROR )
+ m_DeviceCaps.bWireframeFillSupported = False;
+ }
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/SamplerGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/SamplerGLImpl.cpp
new file mode 100644
index 00000000..c26a6a80
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/SamplerGLImpl.cpp
@@ -0,0 +1,124 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "SamplerGLImpl.h"
+#include "RenderDeviceGLImpl.h"
+#include "GLTypeConversions.h"
+
+namespace Diligent
+{
+
+SamplerGLImpl::SamplerGLImpl(class RenderDeviceGLImpl *pDeviceGL, const SamplerDesc& SamplerDesc, bool bIsDeviceInternal) :
+ TSamplerBase( pDeviceGL, SamplerDesc, bIsDeviceInternal ),
+ m_GlSampler(true)
+{
+ const auto& SamCaps = pDeviceGL->GetDeviceCaps().SamCaps;
+
+ Bool bMinAnisotropic = False, bMagAnisotropic = False, bMipAnisotropic = False;
+ Bool bMinComparison = False, bMagComparison = False, bMipComparison = False;
+ GLenum GLMinFilter, GLMagFilter, GLMipFilter;
+ FilterTypeToGLFilterType(SamplerDesc.MinFilter, GLMinFilter, bMinAnisotropic, bMinComparison);
+ FilterTypeToGLFilterType(SamplerDesc.MagFilter, GLMagFilter, bMagAnisotropic, bMagComparison);
+ FilterTypeToGLFilterType(SamplerDesc.MipFilter, GLMipFilter, bMipAnisotropic, bMipComparison);
+ VERIFY( bMinAnisotropic == bMagAnisotropic && bMagAnisotropic == bMipAnisotropic, "Incosistent anisotropy filter setting" );
+ VERIFY( bMinComparison == bMagComparison && bMagComparison == bMipComparison, "Incosistent comparison filter setting" );
+
+ glSamplerParameteri(m_GlSampler, GL_TEXTURE_MAG_FILTER, GLMagFilter);
+
+ GLenum GlMinMipFilter = 0;
+ if( GLMinFilter == GL_NEAREST && GLMipFilter == GL_NEAREST )
+ GlMinMipFilter = GL_NEAREST_MIPMAP_NEAREST;
+ else if( GLMinFilter == GL_LINEAR && GLMipFilter == GL_NEAREST )
+ GlMinMipFilter = GL_LINEAR_MIPMAP_NEAREST;
+ else if( GLMinFilter == GL_NEAREST && GLMipFilter == GL_LINEAR )
+ GlMinMipFilter = GL_NEAREST_MIPMAP_LINEAR;
+ else if( GLMinFilter == GL_LINEAR && GLMipFilter == GL_LINEAR )
+ GlMinMipFilter = GL_LINEAR_MIPMAP_LINEAR;
+ else
+ LOG_ERROR_AND_THROW( "Unsupported min/mip filter combination" );
+ glSamplerParameteri(m_GlSampler, GL_TEXTURE_MIN_FILTER, GlMinMipFilter);
+
+ GLenum WrapModes[3] = { 0 };
+ TEXTURE_ADDRESS_MODE AddressModes[] =
+ {
+ SamplerDesc.AddressU,
+ SamplerDesc.AddressV,
+ SamplerDesc.AddressW
+ };
+ for( int i = 0; i < _countof( AddressModes ); ++i )
+ {
+ auto &WrapMode = WrapModes[i];
+ WrapMode = TexAddressModeToGLAddressMode( AddressModes[i] );
+ if( !SamCaps.bBorderSamplingModeSupported && WrapMode == GL_CLAMP_TO_BORDER )
+ {
+ LOG_ERROR_MESSAGE( "GL_CLAMP_TO_BORDER filtering mode is not supported. Defaulting to GL_CLAMP_TO_EDGE.\n" );
+ WrapMode = GL_CLAMP_TO_EDGE;
+ }
+ }
+ glSamplerParameteri(m_GlSampler, GL_TEXTURE_WRAP_S, WrapModes[0]);
+ glSamplerParameteri(m_GlSampler, GL_TEXTURE_WRAP_T, WrapModes[1]);
+ glSamplerParameteri(m_GlSampler, GL_TEXTURE_WRAP_R, WrapModes[2]);
+
+ if( SamCaps.bLODBiasSupported ) // Can be unsupported
+ glSamplerParameterf(m_GlSampler, GL_TEXTURE_LOD_BIAS, SamplerDesc.MipLODBias);
+ else
+ {
+ if( SamplerDesc.MipLODBias )
+ LOG_WARNING_MESSAGE( "Texture LOD bias sampler attribute is not supported\n" );
+ }
+
+ if( SamCaps.bAnisotropicFilteringSupported ) // Can be unsupported
+ glSamplerParameterf(m_GlSampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, bMipAnisotropic ? static_cast<float>(SamplerDesc.MaxAnisotropy) : 1.f);
+ else
+ {
+ if( bMipAnisotropic && SamplerDesc.MaxAnisotropy != 1 )
+ LOG_WARNING_MESSAGE( "Max anisotropy sampler attribute is not supported\n" );
+ }
+
+ glSamplerParameteri(m_GlSampler, GL_TEXTURE_COMPARE_MODE, bMinComparison ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE);
+
+ if( SamCaps.bBorderSamplingModeSupported ) // Can be unsupported
+ glSamplerParameterfv(m_GlSampler, GL_TEXTURE_BORDER_COLOR, SamplerDesc.BorderColor);
+ else
+ {
+ if( SamplerDesc.BorderColor[0] != 0 || SamplerDesc.BorderColor[1] != 0 || SamplerDesc.BorderColor[2] != 0 || SamplerDesc.BorderColor[3] != 0 )
+ LOG_WARNING_MESSAGE( "Border color sampler attribute is not supported\n" );
+ }
+ GLenum GLCompareFunc = CompareFuncToGLCompareFunc(SamplerDesc.ComparisonFunc);
+ glSamplerParameteri(m_GlSampler, GL_TEXTURE_COMPARE_FUNC, GLCompareFunc);
+
+ glSamplerParameterf(m_GlSampler, GL_TEXTURE_MAX_LOD, SamplerDesc.MaxLOD);
+ glSamplerParameterf(m_GlSampler, GL_TEXTURE_MIN_LOD, SamplerDesc.MinLOD);
+
+ CHECK_GL_ERROR_AND_THROW("Failed to create OpenGL texture sampler\n");
+}
+
+SamplerGLImpl::~SamplerGLImpl()
+{
+
+}
+
+IMPLEMENT_QUERY_INTERFACE( SamplerGLImpl, IID_SamplerGL, TSamplerBase )
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp
new file mode 100644
index 00000000..0f650bdd
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp
@@ -0,0 +1,342 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "ShaderGLImpl.h"
+#include "RenderDeviceGLImpl.h"
+#include "DataBlobImpl.h"
+#include "HLSL2GLSLConverter.h"
+
+using namespace Diligent;
+
+namespace Diligent
+{
+
+static const Char* g_GLSLDefinitions =
+{
+ #include "GLSLDefinitions_inc.h"
+};
+
+ShaderGLImpl::ShaderGLImpl(RenderDeviceGLImpl *pDeviceGL, const ShaderCreationAttribs &ShaderCreationAttribs, bool bIsDeviceInternal) :
+ TShaderBase( pDeviceGL, ShaderCreationAttribs.Desc, bIsDeviceInternal ),
+ m_GlProgObj(false),
+ m_GLShaderObj( false, GLObjectWrappers::GLShaderObjCreateReleaseHelper( GetGLShaderType( m_Desc.ShaderType ) ) )
+{
+ std::vector<const char *> ShaderStrings;
+
+ // Each element in the length array may contain the length of the corresponding string
+ // (the null character is not counted as part of the string length).
+ // Not specifying lengths causes shader compilation errors on Android
+ std::vector<GLint> Lenghts;
+
+ ShaderStrings.push_back(
+#if defined(_WINDOWS)
+ "#version 430 core\n"
+ "#define DESKTOP_GL 1\n"
+#elif defined(ANDROID)
+ "#version 310 es\n"
+
+ "#extension GL_EXT_shader_io_blocks : enable\n" // This is required on NVidia
+
+ "#ifndef GL_ES\n"
+ "# define GL_ES 1\n"
+ "#endif\n"
+
+ "precision highp float;\n"
+ "precision highp int;\n"
+ //"precision highp uint;\n" // This line causes shader compilation error on NVidia!
+
+ "precision highp sampler2D;\n"
+ "precision highp sampler3D;\n"
+ "precision highp samplerCube;\n"
+ "precision highp samplerCubeArray;\n"
+ "precision highp samplerCubeShadow;\n"
+ "precision highp samplerCubeArrayShadow;\n"
+ "precision highp sampler2DShadow;\n"
+ "precision highp sampler2DArray;\n"
+ "precision highp sampler2DArrayShadow;\n"
+ "precision highp sampler2DMS;\n" // ES3.1
+
+ "precision highp isampler2D;\n"
+ "precision highp isampler3D;\n"
+ "precision highp isamplerCube;\n"
+ "precision highp isamplerCubeArray;\n"
+ "precision highp isampler2DArray;\n"
+ "precision highp isampler2DMS;\n" // ES3.1
+
+ "precision highp usampler2D;\n"
+ "precision highp usampler3D;\n"
+ "precision highp usamplerCube;\n"
+ "precision highp usamplerCubeArray;\n"
+ "precision highp usampler2DArray;\n"
+ "precision highp usampler2DMS;\n" // ES3.1
+
+ "precision highp image2D;\n"
+ "precision highp image3D;\n"
+ "precision highp imageCube;\n"
+ "precision highp image2DArray;\n"
+
+ "precision highp iimage2D;\n"
+ "precision highp iimage3D;\n"
+ "precision highp iimageCube;\n"
+ "precision highp iimage2DArray;\n"
+
+ "precision highp uimage2D;\n"
+ "precision highp uimage3D;\n"
+ "precision highp uimageCube;\n"
+ "precision highp uimage2DArray;\n"
+#endif
+ // It would be much more convenient to use row_major matrices.
+ // But unfortunatelly on NVIDIA, the following directive
+ // layout(std140, row_major) uniform;
+ // does not have any effect on matrices that are part of structures
+ // So we have to use column-major matrices which are default in both
+ // DX and GLSL.
+ "layout(std140) uniform;\n"
+ );
+ Lenghts.push_back( static_cast<GLint>( strlen( ShaderStrings.back() ) ) );
+
+ const Char* ShaderTypeDefine = nullptr;
+ switch( m_Desc.ShaderType )
+ {
+ case SHADER_TYPE_VERTEX: ShaderTypeDefine = "#define VERTEX_SHADER\n"; break;
+ case SHADER_TYPE_PIXEL: ShaderTypeDefine = "#define FRAGMENT_SHADER\n"; break;
+ case SHADER_TYPE_GEOMETRY: ShaderTypeDefine = "#define GEOMETRY_SHADER\n"; break;
+ case SHADER_TYPE_HULL: ShaderTypeDefine = "#define TESS_CONTROL_SHADER\n"; break;
+ case SHADER_TYPE_DOMAIN: ShaderTypeDefine = "#define TESS_EVALUATION_SHADER\n";break;
+ case SHADER_TYPE_COMPUTE: ShaderTypeDefine = "#define COMPUTE_SHADER\n"; break;
+ default: UNEXPECTED("Shader type is not specified");
+ }
+ ShaderStrings.push_back( ShaderTypeDefine );
+ Lenghts.push_back( static_cast<GLint>( strlen(ShaderTypeDefine) ) );
+
+ String UserDefines;
+ if( ShaderCreationAttribs.Macros != nullptr)
+ {
+ auto *pMacro = ShaderCreationAttribs.Macros;
+ while( pMacro->Name != nullptr && pMacro->Definition != nullptr )
+ {
+ UserDefines += "#define ";
+ UserDefines += pMacro->Name;
+ UserDefines += ' ';
+ UserDefines += pMacro->Definition;
+ UserDefines += "\n";
+ ++pMacro;
+ }
+ ShaderStrings.push_back( UserDefines.c_str() );
+ Lenghts.push_back( static_cast<GLint>( UserDefines.length() ) );
+ }
+
+ RefCntAutoPtr<Diligent::IDataBlob> pFileData(new Diligent::DataBlobImpl);
+ auto ShaderSource = ShaderCreationAttribs.Source;
+ GLuint SourceLen = 0;
+ if( ShaderSource )
+ {
+ SourceLen = (GLint)strlen(ShaderSource);
+ }
+ else
+ {
+ VERIFY(ShaderCreationAttribs.pShaderSourceStreamFactory, "Input stream factory is null");
+ RefCntAutoPtr<IFileStream> pSourceStream;
+ ShaderCreationAttribs.pShaderSourceStreamFactory->CreateInputStream( ShaderCreationAttribs.FilePath, &pSourceStream );
+ pSourceStream->Read( pFileData );
+ ShaderSource = reinterpret_cast<char*>(pFileData->GetDataPtr());
+ SourceLen = static_cast<GLint>( pFileData->GetSize() );
+ }
+
+ String ConvertedSource;
+ if( ShaderCreationAttribs.SourceLanguage == SHADER_SOURCE_LANGUAGE_HLSL )
+ {
+ ShaderStrings.push_back( g_GLSLDefinitions );
+ static const auto GLSLDefinitionsLen = strlen( g_GLSLDefinitions );
+ Lenghts.push_back( static_cast<GLint>( GLSLDefinitionsLen ) );
+
+ // Convert HLSL to GLSL
+ HLSL2GLSLConverter Converter(ShaderCreationAttribs.pShaderSourceStreamFactory);
+ ConvertedSource = Converter.Convert(ShaderSource, SourceLen, ShaderCreationAttribs.EntryPoint, ShaderCreationAttribs.Desc.ShaderType);
+
+ ShaderSource = ConvertedSource.c_str();
+ SourceLen = static_cast<GLint>( ConvertedSource.length() );
+ }
+
+ ShaderStrings.push_back( ShaderSource );
+ Lenghts.push_back( SourceLen );
+
+ // Note: there is a simpler way to create the program:
+ //m_uiShaderSeparateProg = glCreateShaderProgramv(GL_VERTEX_SHADER, _countof(ShaderStrings), ShaderStrings);
+ // NOTE: glCreateShaderProgramv() is considered equivalent to both a shader compilation and a program linking
+ // operation. Since it performs both at the same time, compiler or linker errors can be encountered. However,
+ // since this function only returns a program object, compiler-type errors will be reported as linker errors
+ // through the following API:
+ // GLint isLinked = 0;
+ // glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
+ // The log can then be queried in the same way
+
+ // Create empty shader object
+ auto GLShaderType = GetGLShaderType(m_Desc.ShaderType);
+ GLObjectWrappers::GLShaderObj ShaderObj(true, GLObjectWrappers::GLShaderObjCreateReleaseHelper(GLShaderType));
+
+ VERIFY( ShaderStrings.size() == Lenghts.size(), "Incosistent array size" );
+
+ // Provide source strings (the strings will be saved in internal OpenGL memory)
+ glShaderSource(ShaderObj, static_cast<GLuint>( ShaderStrings.size() ), ShaderStrings.data(), Lenghts.data() );
+ // When the shader is compiled, it will be compiled as if all of the given strings were concatenated end-to-end.
+ glCompileShader(ShaderObj);
+ GLint compiled = GL_FALSE;
+ // Get compilation status
+ glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &compiled);
+ if(!compiled)
+ {
+ std::stringstream ErrorMsgSS;
+ ErrorMsgSS << "Failed to compile shader file \""<< ShaderCreationAttribs.FilePath << '\"' << std::endl;
+ int infoLogLen = 0;
+ // The function glGetShaderiv() tells how many bytes to allocate; the length includes the NULL terminator.
+ glGetShaderiv(ShaderObj, GL_INFO_LOG_LENGTH, &infoLogLen);
+
+ if (infoLogLen > 0)
+ {
+ std::vector<GLchar> infoLog(infoLogLen);
+ int charsWritten = 0;
+ // Get the log. infoLogLen is the size of infoLog. This tells OpenGL how many bytes at maximum it will write
+ // charsWritten is a return value, specifying how many bytes it actually wrote. One may pass NULL if he
+ // doesn't care
+ glGetShaderInfoLog(ShaderObj, infoLogLen, &charsWritten, infoLog.data());
+ VERIFY(charsWritten == infoLogLen-1, "Unexpected info log length");
+ ErrorMsgSS << "InfoLog:" << std::endl << infoLog.data() << std::endl;
+ }
+ LOG_ERROR_AND_THROW(ErrorMsgSS.str().c_str());
+ }
+
+ auto DeviceCaps = pDeviceGL->GetDeviceCaps();
+ if( DeviceCaps.bSeparableProgramSupported )
+ {
+ m_GlProgObj.Create();
+
+ // GL_PROGRAM_SEPARABLE parameter must be set before linking!
+ glProgramParameteri( m_GlProgObj, GL_PROGRAM_SEPARABLE, GL_TRUE );
+ glAttachShader( m_GlProgObj, ShaderObj );
+ //With separable program objects, interfaces between shader stages may
+ //involve the outputs from one program object and the inputs from a
+ //second program object. For such interfaces, it is not possible to
+ //detect mismatches at link time, because the programs are linked
+ //separately. When each such program is linked, all inputs or outputs
+ //interfacing with another program stage are treated as active. The
+ //linker will generate an executable that assumes the presence of a
+ //compatible program on the other side of the interface. If a mismatch
+ //between programs occurs, no GL error will be generated, but some or all
+ //of the inputs on the interface will be undefined.
+ glLinkProgram( m_GlProgObj );
+ CHECK_GL_ERROR( "glLinkProgram() failed" );
+ int IsLinked = GL_FALSE;
+ glGetProgramiv( m_GlProgObj, GL_LINK_STATUS, (int *)&IsLinked );
+ CHECK_GL_ERROR( "glGetProgramiv() failed" );
+ if( !IsLinked )
+ {
+ int LengthWithNull = 0, Length = 0;
+ // Notice that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv.
+ // The length of the info log includes a null terminator.
+ glGetProgramiv( m_GlProgObj, GL_INFO_LOG_LENGTH, &LengthWithNull );
+
+ // The maxLength includes the NULL character
+ std::vector<char> shaderProgramInfoLog( LengthWithNull );
+
+ // Notice that glGetProgramInfoLog is used, not glGetShaderInfoLog.
+ glGetProgramInfoLog( m_GlProgObj, LengthWithNull, &Length, &shaderProgramInfoLog[0] );
+ VERIFY( Length == LengthWithNull-1, "Incorrect program info log len" );
+ LOG_ERROR_AND_THROW( "Failed to link shader program:\n", &shaderProgramInfoLog[0], '\n');
+ }
+
+ glDetachShader( m_GlProgObj, ShaderObj );
+
+ // glDeleteShader() deletes the shader immediately if it is not attached to any program
+ // object. Otherwise, the shader is flagged for deletion and will be deleted when it is
+ // no longer attached to any program object. If an object is flagged for deletion, its
+ // boolean status bit DELETE_STATUS is set to true
+ ShaderObj.Release();
+
+ m_GlProgObj.LoadUniforms();
+
+ // After all program resources are loaded, we can populate shader variable hash map.
+ // The map contains raw pointers, but none of the arrays will ever change.
+#define STORE_SHADER_VARIABLES(ResArr)\
+ { \
+ auto& Arr = ResArr; \
+ for( auto it = Arr.begin(); it != Arr.end(); ++it ) \
+ /* HashMapStringKey will make a copy of the string*/ \
+ m_VariableHash.insert( std::make_pair( Diligent::HashMapStringKey(it->Name), CGLShaderVariable(this, *it) ) ); \
+ }
+
+ STORE_SHADER_VARIABLES(m_GlProgObj.GetUniformBlocks())
+ STORE_SHADER_VARIABLES(m_GlProgObj.GetSamplers())
+ STORE_SHADER_VARIABLES(m_GlProgObj.GetImages())
+ STORE_SHADER_VARIABLES(m_GlProgObj.GetStorageBlocks())
+#undef STORE_SHADER_VARIABLES
+
+ }
+ else
+ {
+ m_GLShaderObj = std::move( ShaderObj );
+ }
+}
+
+ShaderGLImpl::~ShaderGLImpl()
+{
+ static_cast<RenderDeviceGLImpl*>( GetDevice() )->m_PipelineCache.OnDestroyShader(this);
+}
+
+IMPLEMENT_QUERY_INTERFACE( ShaderGLImpl, IID_ShaderGL, TShaderBase )
+
+void ShaderGLImpl::BindResources( IResourceMapping* pResourceMapping, Uint32 Flags )
+{
+ if( m_GlProgObj )
+ m_GlProgObj.BindResources( pResourceMapping, Flags );
+ else
+ {
+ static bool FirstTime = true;
+ if( FirstTime )
+ {
+ LOG_WARNING_MESSAGE( "IShader::BindResources() effectively does nothing when separable programs are not supported by the device. Use IDeviceContext::BindShaderResources() instead." );
+ FirstTime = false;
+ }
+ }
+}
+
+IShaderVariable* ShaderGLImpl::GetShaderVariable( const Char* Name )
+{
+ if( !m_GlProgObj )
+ {
+ UNSUPPORTED( "Shader variable queries are currently supported for separable programs only" );
+ }
+
+ // Name will be implicitly converted to HashMapStringKey without making a copy
+ auto it = m_VariableHash.find( Name );
+ if( it == m_VariableHash.end() )
+ {
+ LOG_ERROR_MESSAGE( "Shader variable \"", Name, "\" is not found in shader \"", m_Desc.Name ? m_Desc.Name : "", "\". Attempts to set the variable will be silently ignored." );
+ return &m_DummyShaderVar;
+ }
+ return &it->second;
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp
new file mode 100644
index 00000000..42f128df
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp
@@ -0,0 +1,71 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "DeviceContextGLImpl.h"
+#include "RenderDeviceGLImpl.h"
+#include "SwapChainGLImpl.h"
+
+namespace Diligent
+{
+SwapChainGLImpl::SwapChainGLImpl(const SwapChainDesc& SCDesc,
+ RenderDeviceGLImpl* pRenderDeviceGL,
+ DeviceContextGLImpl* pImmediateContextGL) :
+ TSwapChainBase( pRenderDeviceGL, pImmediateContextGL, pRenderDeviceGL->m_GLContext.GetSwapChainDesc() )
+{
+}
+
+SwapChainGLImpl::~SwapChainGLImpl()
+{
+}
+
+IMPLEMENT_QUERY_INTERFACE( SwapChainGLImpl, IID_SwapChainGL, TSwapChainBase )
+
+void SwapChainGLImpl::Present()
+{
+ auto *pDeviceGL = ValidatedCast<RenderDeviceGLImpl>(m_pRenderDevice.RawPtr());
+ pDeviceGL->m_GLContext.SwapBuffers();
+}
+
+void SwapChainGLImpl::Resize( Uint32 NewWidth, Uint32 NewHeight )
+{
+ if( TSwapChainBase::Resize( NewWidth, NewHeight ) )
+ {
+ auto pDeviceContext = m_wpDeviceContext.Lock();
+ VERIFY( pDeviceContext, "Immediate context has been released" );
+ if( pDeviceContext )
+ {
+ auto *pImmediateCtxGL = ValidatedCast<DeviceContextGLImpl>( pDeviceContext.RawPtr() );
+ bool bIsDefaultFBBound = pImmediateCtxGL->IsDefaultFBBound();
+
+ // To update the viewport is the only thing we need to do in OpenGL
+ if( bIsDefaultFBBound )
+ {
+ // Update viewport
+ pImmediateCtxGL->SetViewports( 1, nullptr, 0, 0 );
+ }
+ }
+ }
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp b/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp
new file mode 100644
index 00000000..a853c7ee
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp
@@ -0,0 +1,264 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "TexRegionRender.h"
+#include "RenderDeviceGLImpl.h"
+#include "DeviceContextGLImpl.h"
+#include "MapHelper.h"
+
+namespace Diligent
+{
+ static const Char* VertexShaderSource =
+ {
+ //To use any built-in input or output in the gl_PerVertex and
+ //gl_PerFragment blocks in separable program objects, shader code must
+ //redeclare those blocks prior to use.
+ //
+ // Declaring this block causes compilation error on NVidia GLES
+ "#ifndef GL_ES \n"
+ "out gl_PerVertex \n"
+ "{ \n"
+ " vec4 gl_Position; \n"
+ "}; \n"
+ "#endif \n"
+
+ "void main() \n"
+ "{ \n"
+ " vec4 Bounds = vec4(-1.0, -1.0, 1.0, 1.0); \n"
+ " vec2 PosXY[4] = \n"
+ " { \n"
+ " Bounds.xy, \n"
+ " Bounds.xw, \n"
+ " Bounds.zy, \n"
+ " Bounds.zw \n"
+ " }; \n"
+ " gl_Position = vec4(PosXY[gl_VertexID], 0.0, 1.0);\n"
+ "} \n"
+ };
+
+ TexRegionRender::TexRegionRender( class RenderDeviceGLImpl *pDeviceGL ) :
+ m_OrigStencilRef(0),
+ m_OrigSamplesBlendMask(0),
+ m_NumRenderTargets(0)
+ {
+ memset( m_OrigBlendFactors, 0, sizeof(m_OrigBlendFactors) );
+ memset( m_pOrigRTVs, 0, sizeof( m_pOrigRTVs ) );
+
+ ShaderCreationAttribs ShaderAttrs;
+ ShaderAttrs.Desc.Name = "TexRegionRender : Vertex shader";
+ ShaderAttrs.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ ShaderAttrs.Source = VertexShaderSource;
+ pDeviceGL->CreateShader( ShaderAttrs, &m_pVertexShader,
+ true // We must indicate the shader is internal device object
+ );
+
+ static const char* SamplerType[TEXTURE_TYPE_NUM_TYPES] = {};
+ SamplerType[TEXTURE_TYPE_1D] = "sampler1D";
+ SamplerType[TEXTURE_TYPE_1D_ARRAY] = "sampler1DArray";
+ SamplerType[TEXTURE_TYPE_2D] = "sampler2D";
+ SamplerType[TEXTURE_TYPE_2D_ARRAY] = "sampler2DArray",
+ SamplerType[TEXTURE_TYPE_3D] = "sampler3D";
+ // There is no texelFetch() for texture cube [array]
+ //SamplerType[TEXTURE_TYPE_CUBE] = "samplerCube";
+ //SamplerType[TEXTURE_TYPE_CUBE_ARRAY] = "smaplerCubeArray";
+
+ static const char* SrcLocations[TEXTURE_TYPE_NUM_TYPES] = {};
+ SrcLocations[TEXTURE_TYPE_1D] = "int(gl_FragCoord.x) + Constants.x";
+ SrcLocations[TEXTURE_TYPE_1D_ARRAY] = "ivec2(int(gl_FragCoord.x) + Constants.x, Constants.z)";
+ SrcLocations[TEXTURE_TYPE_2D] = "ivec2(gl_FragCoord.xy) + Constants.xy";
+ SrcLocations[TEXTURE_TYPE_2D_ARRAY] = "ivec3(ivec2(gl_FragCoord.xy) + Constants.xy, Constants.z)",
+ SrcLocations[TEXTURE_TYPE_3D] = "ivec3(ivec2(gl_FragCoord.xy) + Constants.xy, Constants.z)";
+ // There is no texelFetch() for texture cube [array]
+ //CoordDim[TEXTURE_TYPE_CUBE] = "ivec2(gl_FragCoord.xy)";
+ //CoordDim[TEXTURE_TYPE_CUBE_ARRAY] = "ivec2(gl_FragCoord.xy)";
+
+ BufferDesc CBDesc;
+ CBDesc.uiSizeInBytes = sizeof(Int32)*4;
+ CBDesc.Usage = USAGE_DYNAMIC;
+ CBDesc.BindFlags = BIND_UNIFORM_BUFFER;
+ CBDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ pDeviceGL->CreateBuffer( CBDesc, BufferData(), &m_pConstantBuffer,
+ true // We must indicate the buffer is internal device object
+ );
+
+ static const char* CmpTypePrefix[3] = { "", "i", "u" };
+ for( Int32 Dim = TEXTURE_TYPE_2D; Dim <= TEXTURE_TYPE_3D; ++Dim )
+ {
+ const auto *SamplerDim = SamplerType[Dim];
+ const auto *SrcLocation = SrcLocations[Dim];
+ for( Int32 Fmt = 0; Fmt < 3; ++Fmt )
+ {
+ const auto *Prefix = CmpTypePrefix[Fmt];
+ String Name = "TexRegionRender : Pixel shader ";
+ Name.append( Prefix );
+ Name.append( SamplerDim );
+ ShaderAttrs.Desc.Name = Name.c_str();
+ ShaderAttrs.Desc.ShaderType = SHADER_TYPE_PIXEL;
+
+ std::stringstream SourceSS;
+ SourceSS << "uniform " << Prefix << SamplerDim << " gSourceTex;\n"
+ << "layout( location = 0 ) out " << Prefix << "vec4 Out;\n"
+ << "uniform cbConstants\n"
+ << "{\n"
+ << " ivec4 Constants;\n"
+ << "};\n"
+ << "void main()\n"
+ << "{\n"
+ << " Out = texelFetch( gSourceTex, " << SrcLocation << ", Constants.w );\n"
+ << "}\n";
+
+ auto Source = SourceSS.str();
+ ShaderAttrs.Source = Source.c_str();
+ auto &FragmetShader = m_pFragmentShaders[Dim*3 + Fmt];
+ pDeviceGL->CreateShader( ShaderAttrs, &FragmetShader,
+ true // We must indicate the shader is internal device object
+ );
+ FragmetShader->GetShaderVariable( "cbConstants" )->Set( m_pConstantBuffer );
+ }
+ }
+
+ RasterizerStateDesc RSDesc;
+ RSDesc.CullMode = CULL_MODE_NONE;
+ RSDesc.FillMode = FILL_MODE_SOLID;
+ RSDesc.Name = "TexRegionRender : Solid fill no cull RS";
+ pDeviceGL->CreateRasterizerState( RSDesc, &m_pSolidFillNoCullRS,
+ true // We must indicate the RS state is internal device object
+ );
+
+ DepthStencilStateDesc DSSDesc;
+ DSSDesc.Name = "TexRegionRender : disable depth DSS";
+ DSSDesc.DepthEnable = false;
+ DSSDesc.DepthWriteEnable = false;
+ pDeviceGL->CreateDepthStencilState( DSSDesc, &m_pDisableDetphDS,
+ true // We must indicate the DSS state is internal device object
+ );
+
+ BlendStateDesc BSDesc;
+ BSDesc.Name = "TexRegionRender : default BS";
+ pDeviceGL->CreateBlendState(BSDesc, &m_pDefaultBS,
+ true // We must indicate the BS state is internal device object
+ );
+ }
+
+ void TexRegionRender::SetStates( DeviceContextGLImpl *pCtxGL )
+ {
+ Uint32 NumShaders = 0;
+ pCtxGL->GetShaders( nullptr, NumShaders );
+ m_pOrigShaders.resize( NumShaders );
+ pCtxGL->GetShaders( m_pOrigShaders.data(), NumShaders );
+
+ pCtxGL->GetRenderTargets( m_NumRenderTargets, m_pOrigRTVs, &m_pOrigDSV );
+
+ Uint32 NumViewports = 0;
+ pCtxGL->GetViewports( NumViewports, nullptr );
+ m_OrigViewports.resize(NumViewports);
+ pCtxGL->GetViewports( NumViewports, m_OrigViewports.data() );
+
+ pCtxGL->GetDepthStencilState(&m_pOrigDS, m_OrigStencilRef);
+ VERIFY( m_pOrigDS, "At least default depth-stencil state must be bound" );
+
+ pCtxGL->GetBlendState(&m_pOrigBS, m_OrigBlendFactors, m_OrigSamplesBlendMask);
+ VERIFY( m_pOrigBS, "At least default blend state must be bound" );
+
+ pCtxGL->GetRasterizerState(&m_pOrigRS);
+ VERIFY( m_pOrigRS, "At least default rasterizer state must be bound" );
+
+ pCtxGL->SetDepthStencilState( m_pDisableDetphDS, m_OrigStencilRef );
+ pCtxGL->SetBlendState(m_pDefaultBS, m_OrigBlendFactors, m_OrigSamplesBlendMask);
+ pCtxGL->SetRasterizerState(m_pSolidFillNoCullRS);
+
+ }
+
+ void TexRegionRender::RestoreStates( DeviceContextGLImpl *pCtxGL )
+ {
+ pCtxGL->SetShaders( m_pOrigShaders.data(), (Uint32)m_pOrigShaders.size() );
+ for( auto pSh = m_pOrigShaders.begin(); pSh != m_pOrigShaders.end(); ++pSh )
+ (*pSh)->Release();
+ m_pOrigShaders.clear();
+
+ pCtxGL->SetRenderTargets( m_NumRenderTargets, m_pOrigRTVs, m_pOrigDSV );
+ for( Uint32 rt = 0; rt < _countof( m_pOrigRTVs ); ++rt )
+ {
+ if( m_pOrigRTVs[rt] )
+ m_pOrigRTVs[rt]->Release();
+ m_pOrigRTVs[rt] = nullptr;
+ }
+ m_pOrigDSV.Release();
+
+ pCtxGL->SetViewports( (Uint32)m_OrigViewports.size(), m_OrigViewports.data(), 0, 0 );
+
+ pCtxGL->SetDepthStencilState( m_pOrigDS, m_OrigStencilRef );
+ m_pOrigDS.Release();
+
+ pCtxGL->SetBlendState(m_pOrigBS, m_OrigBlendFactors, m_OrigSamplesBlendMask);
+ m_pOrigBS.Release();
+
+ pCtxGL->SetRasterizerState(m_pOrigRS);
+ m_pOrigRS.Release();
+ }
+
+ void TexRegionRender::Render( DeviceContextGLImpl *pCtxGL,
+ ITextureView *pSrcSRV,
+ TEXTURE_TYPE TexType,
+ TEXTURE_FORMAT TexFormat,
+ Int32 DstToSrcXOffset,
+ Int32 DstToSrcYOffset,
+ Int32 SrcZ,
+ Int32 SrcMipLevel)
+ {
+ {
+ MapHelper< int > pConstant( pCtxGL, m_pConstantBuffer, MAP_WRITE_DISCARD, 0 );
+ pConstant[0] = DstToSrcXOffset;
+ pConstant[1] = DstToSrcYOffset;
+ pConstant[2] = SrcZ;
+ pConstant[3] = SrcMipLevel;
+ }
+
+ const auto &TexFmtAttribs = GetTextureFormatAttribs(TexFormat);
+ Uint32 FSInd = TexType * 3;
+ if( TexFmtAttribs.ComponentType == COMPONENT_TYPE_SINT )
+ FSInd += 1;
+ else if( TexFmtAttribs.ComponentType == COMPONENT_TYPE_UINT )
+ FSInd += 2;
+
+ if( TexFmtAttribs.ComponentType == COMPONENT_TYPE_SNORM )
+ {
+ LOG_WARNING_MESSAGE("CopyData() is performed by rendering to texture.\n"
+ "There might be an issue in OpenGL driver on NVidia hardware: when rendering to SNORM textures, all negative values are clamped to zero.")
+ }
+
+ IShader *ppShaders[2] = { m_pVertexShader, m_pFragmentShaders[FSInd] };
+ auto SrcTexVar = ppShaders[1]->GetShaderVariable( "gSourceTex" );
+ SrcTexVar->Set( pSrcSRV );
+
+ pCtxGL->SetShaders( ppShaders, _countof(ppShaders) );
+ DrawAttribs DrawAttrs;
+ DrawAttrs.NumVertices = 4;
+ DrawAttrs.Topology = PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ pCtxGL->Draw( DrawAttrs );
+
+ SrcTexVar->Set( nullptr );
+ }
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture1DArray_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture1DArray_OGL.cpp
new file mode 100644
index 00000000..8680f788
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/Texture1DArray_OGL.cpp
@@ -0,0 +1,156 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "Texture1DArray_OGL.h"
+#include "RenderDeviceGLImpl.h"
+#include "DeviceContextGLImpl.h"
+#include "GLTypeConversions.h"
+
+
+namespace Diligent
+{
+
+Texture1DArray_OGL::Texture1DArray_OGL( class RenderDeviceGLImpl *pDeviceGL,
+ class DeviceContextGLImpl *pDeviceContext,
+ const TextureDesc& TexDesc,
+ const TextureData &InitData /*= TextureData()*/,
+ bool bIsDeviceInternal /*= false*/) :
+ TextureBaseGL(pDeviceGL, TexDesc, InitData, bIsDeviceInternal)
+{
+ auto &ContextState = pDeviceContext->GetContextState();
+
+ m_BindTarget = GL_TEXTURE_1D_ARRAY;
+ ContextState.BindTexture(-1, m_BindTarget, m_GlTexture);
+
+ // levels format width height
+ glTexStorage2D(m_BindTarget, m_Desc.MipLevels, m_GLTexFormat, m_Desc.Width, m_Desc.ArraySize);
+ CHECK_GL_ERROR_AND_THROW("Failed to allocate storage for the 1D texture array");
+ // When target is GL_TEXTURE_1D_ARRAY, calling glTexStorage2D() is equivalent to the following code:
+ //for (i = 0; i < levels; i++)
+ //{
+ // glTexImage2D(target, i, internalformat, width, height, 0, format, type, NULL);
+ // width = max(1, (width / 2));
+ //}
+
+ SetDefaultGLParameters();
+
+ if( InitData.pSubResources )
+ {
+ if( m_Desc.MipLevels * m_Desc.ArraySize == InitData.NumSubresources )
+ {
+ for(Uint32 Slice = 0; Slice < m_Desc.ArraySize; ++Slice )
+ {
+ for(Uint32 Mip = 0; Mip < m_Desc.MipLevels; ++Mip)
+ {
+ Box DstBox(0, std::max(m_Desc.Width>>Mip, 1U),
+ 0, 1 );
+ // UpdateData() is a virtual function. If we try to call it through vtbl from here,
+ // we will get into TextureBaseGL::UpdateData(), because instance of Texture1DArray_OGL
+ // is not fully constructed yet.
+ // To call the required function, we need to explicitly specify the class:
+ Texture1DArray_OGL::UpdateData(pDeviceContext, Mip, Slice, DstBox, InitData.pSubResources[Slice*m_Desc.MipLevels + Mip]);
+ }
+ }
+ }
+ else
+ {
+ UNEXPECTED("Incorrect number of subresources");
+ }
+ }
+
+ ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj( false ) );
+}
+
+Texture1DArray_OGL::~Texture1DArray_OGL()
+{
+}
+
+void Texture1DArray_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )
+{
+ TextureBaseGL::UpdateData(pContext, MipLevel, Slice, DstBox, SubresData);
+
+ auto *pDeviceContextGL = ValidatedCast<DeviceContextGLImpl>(pContext);
+ auto &ContextState = pDeviceContextGL->GetContextState();
+
+ // GL_TEXTURE_UPDATE_BARRIER_BIT:
+ // Writes to a texture via glTex( Sub )Image*, glCopyTex( Sub )Image*, glClearTex*Image,
+ // glCompressedTex( Sub )Image*, and reads via glTexImage() after the barrier will reflect
+ // data written by shaders prior to the barrier. Additionally, texture writes from these
+ // commands issued after the barrier will not execute until all shader writes initiated prior
+ // to the barrier complete
+ TextureMemoryBarrier( GL_TEXTURE_UPDATE_BARRIER_BIT, ContextState );
+
+ ContextState.BindTexture( -1, m_BindTarget, m_GlTexture );
+
+ // Transfers to OpenGL memory are called unpack operations
+ // If there is a buffer bound to GL_PIXEL_UNPACK_BUFFER target, then all the pixel transfer
+ // operations will be performed from this buffer. We need to make sure none is bound
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+ auto TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0 );
+
+ glTexSubImage2D(m_BindTarget, MipLevel,
+ DstBox.MinX,
+ Slice,
+ DstBox.MaxX - DstBox.MinX,
+ 1,
+ TransferAttribs.PixelFormat, TransferAttribs.DataType,
+ SubresData.pData);
+
+ CHECK_GL_ERROR("Failed to update subimage data");
+
+ ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) );
+}
+
+void Texture1DArray_OGL::AttachToFramebuffer( const TextureViewDesc& ViewDesc, GLenum AttachmentPoint )
+{
+ if( ViewDesc.NumArraySlices == m_Desc.ArraySize )
+ {
+ glFramebufferTexture( GL_DRAW_FRAMEBUFFER, AttachmentPoint, m_GlTexture, ViewDesc.MostDetailedMip );
+ CHECK_GL_ERROR( "Failed to attach texture 1D array to draw framebuffer" );
+ glFramebufferTexture( GL_READ_FRAMEBUFFER, AttachmentPoint, m_GlTexture, ViewDesc.MostDetailedMip );
+ CHECK_GL_ERROR( "Failed to attach texture 1D array to read framebuffer" );
+ }
+ else if( ViewDesc.NumArraySlices == 1 )
+ {
+ // Texture name must either be zero or the name of an existing 3D texture, 1D or 2D array texture,
+ // cube map array texture, or multisample array texture.
+ glFramebufferTextureLayer( GL_DRAW_FRAMEBUFFER, AttachmentPoint, m_GlTexture, ViewDesc.MostDetailedMip, ViewDesc.FirstArraySlice );
+ CHECK_GL_ERROR( "Failed to attach texture 1D array to draw framebuffer" );
+ glFramebufferTextureLayer( GL_READ_FRAMEBUFFER, AttachmentPoint, m_GlTexture, ViewDesc.MostDetailedMip, ViewDesc.FirstArraySlice );
+ CHECK_GL_ERROR( "Failed to attach texture 1D array to read framebuffer" );
+ }
+ else
+ {
+ UNEXPECTED( "Only one slice or the entire texture array can be attached to a framebuffer" );
+ }
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture1D_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture1D_OGL.cpp
new file mode 100644
index 00000000..5b9a0b9a
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/Texture1D_OGL.cpp
@@ -0,0 +1,135 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "Texture1D_OGL.h"
+#include "RenderDeviceGLImpl.h"
+#include "DeviceContextGLImpl.h"
+#include "GLTypeConversions.h"
+
+namespace Diligent
+{
+
+Texture1D_OGL::Texture1D_OGL( class RenderDeviceGLImpl *pDeviceGL,
+ class DeviceContextGLImpl *pDeviceContext,
+ const TextureDesc& TexDesc,
+ const TextureData &InitData /*= TextureData()*/,
+ bool bIsDeviceInternal /*= false*/) :
+ TextureBaseGL(pDeviceGL, TexDesc, InitData, bIsDeviceInternal)
+{
+ auto *pDeviceContextGL = ValidatedCast<DeviceContextGLImpl>(pDeviceContext);
+ auto &ContextState = pDeviceContextGL->GetContextState();
+
+ m_BindTarget = GL_TEXTURE_1D;
+ ContextState.BindTexture(-1, m_BindTarget, m_GlTexture);
+
+ // levels format width
+ glTexStorage1D(m_BindTarget, m_Desc.MipLevels, m_GLTexFormat, m_Desc.Width);
+ CHECK_GL_ERROR_AND_THROW("Failed to allocate storage for the 1D texture");
+ // When target is GL_TEXTURE_1D, calling glTexStorage1D is equivalent to the following pseudo-code:
+ //for (i = 0; i < levels; i++)
+ //{
+ // glTexImage1D(target, i, internalformat, width, 0, format, type, NULL);
+ // width = max(1, (width / 2));
+ //}
+
+ SetDefaultGLParameters();
+
+ if( InitData.pSubResources )
+ {
+ if( m_Desc.MipLevels == InitData.NumSubresources )
+ {
+ for(Uint32 Mip = 0; Mip < m_Desc.MipLevels; ++Mip)
+ {
+ Box DstBox(0, std::max(m_Desc.Width>>Mip, 1U),
+ 0, 1);
+ // UpdateData() is a virtual function. If we try to call it through vtbl from here,
+ // we will get into TextureBaseGL::UpdateData(), because instance of Texture1D_OGL
+ // is not fully constructed yet.
+ // To call the required function, we need to explicitly specify the class:
+ Texture1D_OGL::UpdateData( pDeviceContext, Mip, 0, DstBox, InitData.pSubResources[Mip] );
+ }
+ }
+ else
+ {
+ UNEXPECTED( "Incorrect number of subresources" );
+ }
+ }
+
+ ContextState.BindTexture(-1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) );
+}
+
+Texture1D_OGL::~Texture1D_OGL()
+{
+}
+
+void Texture1D_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )
+{
+ TextureBaseGL::UpdateData(pContext, MipLevel, Slice, DstBox, SubresData);
+
+ auto *pDeviceContextGL = ValidatedCast<DeviceContextGLImpl>(pContext);
+ auto &ContextState = pDeviceContextGL->GetContextState();
+
+ // GL_TEXTURE_UPDATE_BARRIER_BIT:
+ // Writes to a texture via glTex( Sub )Image*, glCopyTex( Sub )Image*, glClearTex*Image,
+ // glCompressedTex( Sub )Image*, and reads via glTexImage() after the barrier will reflect
+ // data written by shaders prior to the barrier. Additionally, texture writes from these
+ // commands issued after the barrier will not execute until all shader writes initiated prior
+ // to the barrier complete
+ TextureMemoryBarrier( GL_TEXTURE_UPDATE_BARRIER_BIT, ContextState );
+
+ ContextState.BindTexture( -1, m_BindTarget, m_GlTexture );
+
+ // Transfers to OpenGL memory are called unpack operations
+ // If there is a buffer bound to GL_PIXEL_UNPACK_BUFFER target, then all the pixel transfer
+ // operations will be performed from this buffer. We need to make sure none is bound
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+ auto TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0 );
+
+ glTexSubImage1D(m_BindTarget, MipLevel,
+ DstBox.MinX,
+ DstBox.MaxX - DstBox.MinX,
+ TransferAttribs.PixelFormat, TransferAttribs.DataType,
+ SubresData.pData);
+ CHECK_GL_ERROR("Failed to update subimage data");
+
+ ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) );
+}
+
+void Texture1D_OGL::AttachToFramebuffer( const TextureViewDesc& ViewDesc, GLenum AttachmentPoint )
+{
+ // For glFramebufferTexture1D(), if texture name is not zero, then texture target must be GL_TEXTURE_1D
+ glFramebufferTexture1D( GL_DRAW_FRAMEBUFFER, AttachmentPoint, m_BindTarget, m_GlTexture, ViewDesc.MostDetailedMip );
+ CHECK_GL_ERROR( "Failed to attach texture 1D to draw framebuffer" );
+ glFramebufferTexture1D( GL_READ_FRAMEBUFFER, AttachmentPoint, m_BindTarget, m_GlTexture, ViewDesc.MostDetailedMip );
+ CHECK_GL_ERROR( "Failed to attach texture 1D to read framebuffer" );
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture2DArray_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture2DArray_OGL.cpp
new file mode 100644
index 00000000..fefa51e5
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/Texture2DArray_OGL.cpp
@@ -0,0 +1,217 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "Texture2DArray_OGL.h"
+#include "RenderDeviceGLImpl.h"
+#include "DeviceContextGLImpl.h"
+#include "GLTypeConversions.h"
+#include "GraphicsUtilities.h"
+
+namespace Diligent
+{
+
+Texture2DArray_OGL::Texture2DArray_OGL( class RenderDeviceGLImpl *pDeviceGL,
+ class DeviceContextGLImpl *pDeviceContext,
+ const TextureDesc& TexDesc,
+ const TextureData &InitData /*= TextureData()*/,
+ bool bIsDeviceInternal /*= false*/) :
+ TextureBaseGL(pDeviceGL, TexDesc, InitData, bIsDeviceInternal)
+{
+ auto &ContextState = pDeviceContext->GetContextState();
+
+ if( m_Desc.SampleCount > 1 )
+ {
+ m_BindTarget = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
+ ContextState.BindTexture(-1, m_BindTarget, m_GlTexture);
+ // format width height depth
+ glTexStorage3DMultisample(m_BindTarget, m_Desc.SampleCount, m_GLTexFormat, m_Desc.Width, m_Desc.Height, m_Desc.ArraySize, TRUE);
+ // The last parameter specifies whether the image will use identical sample locations and the same number of
+ // samples for all texels in the image, and the sample locations will not depend on the internal format or size
+ // of the image.
+ CHECK_GL_ERROR_AND_THROW("Failed to allocate storage for the 2D multisample texture array");
+ // * An INVALID_ENUM error is generated if sizedinternalformat is not colorrenderable,
+ // depth - renderable, or stencil - renderable
+ // * An INVALID_OPERATION error is generated if samples is greater than the maximum number of samples
+ // supported for this target and internalformat. The maximum number of samples supported can be
+ // determined by calling glGetInternalformativ with a pname of GL_SAMPLES
+
+ SetDefaultGLParameters();
+ }
+ else
+ {
+ m_BindTarget = GL_TEXTURE_2D_ARRAY;
+ ContextState.BindTexture(-1, m_BindTarget, m_GlTexture);
+ // levels format width height depth
+ glTexStorage3D(m_BindTarget, m_Desc.MipLevels, m_GLTexFormat, m_Desc.Width, m_Desc.Height, m_Desc.ArraySize);
+ CHECK_GL_ERROR_AND_THROW("Failed to allocate storage for the 2D texture array");
+ // When target is GL_TEXTURE_2D_ARRAY, calling glTexStorage3D is equivalent to the following pseudo-code:
+ //for (i = 0; i < levels; i++)
+ //{
+ // glTexImage3D(target, i, internalformat, width, height, depth, 0, format, type, NULL);
+ // width = max(1, (width / 2));
+ // height = max(1, (height / 2));
+ //}
+
+ SetDefaultGLParameters();
+
+ if( InitData.pSubResources )
+ {
+ if( m_Desc.MipLevels * m_Desc.ArraySize == InitData.NumSubresources )
+ {
+ for(Uint32 Slice = 0; Slice < m_Desc.ArraySize; ++Slice)
+ {
+ for(Uint32 Mip = 0; Mip < m_Desc.MipLevels; ++Mip)
+ {
+ Box DstBox(0, std::max(m_Desc.Width >>Mip, 1U),
+ 0, std::max(m_Desc.Height>>Mip, 1U) );
+ // UpdateData() is a virtual function. If we try to call it through vtbl from here,
+ // we will get into TextureBaseGL::UpdateData(), because instance of Texture2DArray_OGL
+ // is not fully constructed yet.
+ // To call the required function, we need to explicitly specify the class:
+ Texture2DArray_OGL::UpdateData(pDeviceContext, Mip, Slice, DstBox, InitData.pSubResources[Slice*m_Desc.MipLevels + Mip]);
+ }
+ }
+ }
+ else
+ {
+ UNEXPECTED("Incorrect number of subresources");
+ }
+ }
+
+ }
+
+ ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) );
+}
+
+Texture2DArray_OGL::~Texture2DArray_OGL()
+{
+}
+
+void Texture2DArray_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )
+{
+ TextureBaseGL::UpdateData(pContext, MipLevel, Slice, DstBox, SubresData);
+
+ auto *pDeviceContextGL = ValidatedCast<DeviceContextGLImpl>(pContext);
+ auto &ContextState = pDeviceContextGL->GetContextState();
+
+ // GL_TEXTURE_UPDATE_BARRIER_BIT:
+ // Writes to a texture via glTex( Sub )Image*, glCopyTex( Sub )Image*, glClearTex*Image,
+ // glCompressedTex( Sub )Image*, and reads via glTexImage() after the barrier will reflect
+ // data written by shaders prior to the barrier. Additionally, texture writes from these
+ // commands issued after the barrier will not execute until all shader writes initiated prior
+ // to the barrier complete
+ TextureMemoryBarrier( GL_TEXTURE_UPDATE_BARRIER_BIT, ContextState );
+
+ ContextState.BindTexture(-1, m_BindTarget, m_GlTexture);
+
+ // Transfers to OpenGL memory are called unpack operations
+ // If there is a buffer bound to GL_PIXEL_UNPACK_BUFFER target, then all the pixel transfer
+ // operations will be performed from this buffer. We need to make sure none is bound
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+ auto TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+ if( TransferAttribs.IsCompressed )
+ {
+ VERIFY( (DstBox.MinX % 4) == 0 && (DstBox.MinY % 4) == 0 &&
+ ((DstBox.MaxX % 4) == 0 || DstBox.MaxX == std::max(m_Desc.Width >>MipLevel, 1U)) &&
+ ((DstBox.MaxY % 4) == 0 || DstBox.MaxY == std::max(m_Desc.Height>>MipLevel, 1U)),
+ "Compressed texture update region must be 4 pixel-aligned" );
+ const auto &FmtAttribs = GetTextureFormatAttribs(m_Desc.Format);
+ auto BlockBytesInRow = ((DstBox.MaxX - DstBox.MinX + 3)/4) * FmtAttribs.ComponentSize;
+ VERIFY( SubresData.Stride == BlockBytesInRow,
+ "Compressed data stride (", SubresData.Stride, " must match the size of a row of compressed blocks (", BlockBytesInRow, ")" );
+
+ //glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ //glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, 0);
+ glCompressedTexSubImage3D(m_BindTarget, MipLevel,
+ DstBox.MinX,
+ DstBox.MinY,
+ Slice,
+ DstBox.MaxX - DstBox.MinX,
+ DstBox.MaxY - DstBox.MinY,
+ 1,
+ // The format must be the same compressed-texture format previously
+ // specified by glTexStorage2D() (thank you OpenGL for another useless
+ // parameter that is nothing but the source of confusion), otherwise
+ // INVALID_OPERATION error is generated.
+ m_GLTexFormat,
+ // An INVALID_VALUE error is generated if imageSize is not consistent with
+ // the format, dimensions, and contents of the compressed image( too little or
+ // too much data ),
+ ((DstBox.MaxY - DstBox.MinY + 3)/4) * SubresData.Stride,
+ SubresData.pData);
+ }
+ else
+ {
+ const auto TexFmtInfo = GetTextureFormatAttribs(m_Desc.Format);
+ const auto PixelSize = TexFmtInfo.NumComponents * TexFmtInfo.ComponentSize;
+ VERIFY( (SubresData.Stride % PixelSize)==0, "Data stride is not multiple of pixel size" );
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, SubresData.Stride / PixelSize);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0 );
+
+ glTexSubImage3D(m_BindTarget, MipLevel,
+ DstBox.MinX,
+ DstBox.MinY,
+ Slice,
+ DstBox.MaxX - DstBox.MinX,
+ DstBox.MaxY - DstBox.MinY,
+ 1,
+ TransferAttribs.PixelFormat, TransferAttribs.DataType,
+ SubresData.pData);
+ }
+ CHECK_GL_ERROR("Failed to update subimage data");
+
+ ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) );
+}
+
+void Texture2DArray_OGL::AttachToFramebuffer( const TextureViewDesc& ViewDesc, GLenum AttachmentPoint )
+{
+ if( ViewDesc.NumArraySlices == m_Desc.ArraySize )
+ {
+ glFramebufferTexture( GL_DRAW_FRAMEBUFFER, AttachmentPoint, m_GlTexture, ViewDesc.MostDetailedMip );
+ CHECK_GL_ERROR( "Failed to attach texture 2D array to draw framebuffer" );
+ glFramebufferTexture( GL_READ_FRAMEBUFFER, AttachmentPoint, m_GlTexture, ViewDesc.MostDetailedMip );
+ CHECK_GL_ERROR( "Failed to attach texture 2D array to read framebuffer" );
+ }
+ else if( ViewDesc.NumArraySlices == 1 )
+ {
+ // Texture name must either be zero or the name of an existing 3D texture, 1D or 2D array texture,
+ // cube map array texture, or multisample array texture.
+ glFramebufferTextureLayer( GL_DRAW_FRAMEBUFFER, AttachmentPoint, m_GlTexture, ViewDesc.MostDetailedMip, ViewDesc.FirstArraySlice );
+ CHECK_GL_ERROR( "Failed to attach texture 2D array to draw framebuffer" );
+ glFramebufferTextureLayer( GL_READ_FRAMEBUFFER, AttachmentPoint, m_GlTexture, ViewDesc.MostDetailedMip, ViewDesc.FirstArraySlice );
+ CHECK_GL_ERROR( "Failed to attach texture 2D array to read framebuffer" );
+ }
+ else
+ {
+ UNEXPECTED( "Only one slice or the entire texture array can be attached to a framebuffer" );
+ }
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture2D_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture2D_OGL.cpp
new file mode 100644
index 00000000..511085ca
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/Texture2D_OGL.cpp
@@ -0,0 +1,197 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "Texture2D_OGL.h"
+#include "RenderDeviceGLImpl.h"
+#include "DeviceContextGLImpl.h"
+#include "GLTypeConversions.h"
+#include "GraphicsUtilities.h"
+
+namespace Diligent
+{
+
+Texture2D_OGL::Texture2D_OGL( class RenderDeviceGLImpl *pDeviceGL,
+ class DeviceContextGLImpl *pDeviceContext,
+ const TextureDesc& TexDesc,
+ const TextureData &InitData /*= TextureData()*/,
+ bool bIsDeviceInternal /*= false*/) :
+ TextureBaseGL(pDeviceGL, TexDesc, InitData, bIsDeviceInternal)
+{
+ auto &ContextState = pDeviceContext->GetContextState();
+
+ if( m_Desc.SampleCount > 1 )
+ {
+ m_BindTarget = GL_TEXTURE_2D_MULTISAMPLE;
+ ContextState.BindTexture(-1, m_BindTarget, m_GlTexture);
+ // format width height depth
+ glTexStorage2DMultisample(m_BindTarget, m_Desc.SampleCount, m_GLTexFormat, m_Desc.Width, m_Desc.Height, GL_TRUE);
+ // The last parameter specifies whether the image will use identical sample locations and the same number of
+ // samples for all texels in the image, and the sample locations will not depend on the internal format or size
+ // of the image.
+ CHECK_GL_ERROR_AND_THROW("Failed to allocate storage for the 2D multisample texture");
+ // * An INVALID_ENUM error is generated if sizedinternalformat is not colorrenderable,
+ // depth - renderable, or stencil - renderable
+ // * An INVALID_OPERATION error is generated if samples is greater than the maximum number of samples
+ // supported for this target and internalformat. The maximum number of samples supported can be
+ // determined by calling glGetInternalformativ with a pname of GL_SAMPLES
+
+ SetDefaultGLParameters();
+
+ VERIFY( InitData.pSubResources == nullptr, "Multisampled textures cannot be modified directly" );
+ }
+ else
+ {
+ m_BindTarget = GL_TEXTURE_2D;
+ ContextState.BindTexture(-1, m_BindTarget, m_GlTexture);
+ // levels format width height
+ glTexStorage2D(m_BindTarget, m_Desc.MipLevels, m_GLTexFormat, m_Desc.Width, m_Desc.Height);
+ CHECK_GL_ERROR_AND_THROW("Failed to allocate storage for the 2D texture");
+ // When target is GL_TEXTURE_2D, calling glTexStorage2D is equivalent to the following pseudo-code:
+ //for (i = 0; i < levels; i++)
+ //{
+ // glTexImage2D(target, i, internalformat, width, height, 0, format, type, NULL);
+ // width = max(1, (width / 2));
+ // height = max(1, (height / 2));
+ //}
+
+ SetDefaultGLParameters();
+
+ if( InitData.pSubResources )
+ {
+ if( m_Desc.MipLevels == InitData.NumSubresources )
+ {
+ for(Uint32 Mip = 0; Mip < m_Desc.MipLevels; ++Mip)
+ {
+ Box DstBox(0, std::max(m_Desc.Width >>Mip, 1U),
+ 0, std::max(m_Desc.Height>>Mip, 1U) );
+ // UpdateData() is a virtual function. If we try to call it through vtbl from here,
+ // we will get into TextureBaseGL::UpdateData(), because instance of Texture2D_OGL
+ // is not fully constructed yet.
+ // To call the required function, we need to explicitly specify the class:
+ Texture2D_OGL::UpdateData( pDeviceContext, Mip, 0, DstBox, InitData.pSubResources[Mip] );
+ }
+ }
+ else
+ {
+ UNEXPECTED("Incorrect number of subresources");
+ }
+ }
+ }
+
+ ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) );
+}
+
+Texture2D_OGL::~Texture2D_OGL()
+{
+}
+
+void Texture2D_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )
+{
+ TextureBaseGL::UpdateData(pContext, MipLevel, Slice, DstBox, SubresData);
+
+ auto *pDeviceContextGL = ValidatedCast<DeviceContextGLImpl>(pContext);
+ auto &ContextState = pDeviceContextGL->GetContextState();
+
+ // GL_TEXTURE_UPDATE_BARRIER_BIT:
+ // Writes to a texture via glTex( Sub )Image*, glCopyTex( Sub )Image*, glClearTex*Image,
+ // glCompressedTex( Sub )Image*, and reads via glTexImage() after the barrier will reflect
+ // data written by shaders prior to the barrier. Additionally, texture writes from these
+ // commands issued after the barrier will not execute until all shader writes initiated prior
+ // to the barrier complete
+ TextureMemoryBarrier( GL_TEXTURE_UPDATE_BARRIER_BIT, ContextState );
+
+ ContextState.BindTexture(-1, m_BindTarget, m_GlTexture);
+
+ // Transfers to OpenGL memory are called unpack operations
+ // If there is a buffer bound to GL_PIXEL_UNPACK_BUFFER target, then all the pixel transfer
+ // operations will be performed from this buffer. We need to make sure none is bound
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+ auto TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+ if( TransferAttribs.IsCompressed )
+ {
+ VERIFY( (DstBox.MinX % 4) == 0 && (DstBox.MinY % 4) == 0 &&
+ ((DstBox.MaxX % 4) == 0 || DstBox.MaxX == std::max(m_Desc.Width >>MipLevel, 1U)) &&
+ ((DstBox.MaxY % 4) == 0 || DstBox.MaxY == std::max(m_Desc.Height>>MipLevel, 1U)),
+ "Compressed texture update region must be 4 pixel-aligned" );
+ const auto &FmtAttribs = GetTextureFormatAttribs(m_Desc.Format);
+ auto BlockBytesInRow = ((DstBox.MaxX - DstBox.MinX + 3)/4) * FmtAttribs.ComponentSize;
+ VERIFY( SubresData.Stride == BlockBytesInRow,
+ "Compressed data stride (", SubresData.Stride, " must match the size of a row of compressed blocks (", BlockBytesInRow, ")" );
+
+ //glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ //glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, 0);
+ glCompressedTexSubImage2D(m_BindTarget, MipLevel,
+ DstBox.MinX,
+ DstBox.MinY,
+ DstBox.MaxX - DstBox.MinX,
+ DstBox.MaxY - DstBox.MinY,
+ // The format must be the same compressed-texture format previously
+ // specified by glTexStorage2D() (thank you OpenGL for another useless
+ // parameter that is nothing but the source of confusion), otherwise
+ // INVALID_OPERATION error is generated.
+ m_GLTexFormat,
+ // An INVALID_VALUE error is generated if imageSize is not consistent with
+ // the format, dimensions, and contents of the compressed image( too little or
+ // too much data ),
+ ((DstBox.MaxY - DstBox.MinY + 3)/4) * SubresData.Stride,
+ SubresData.pData);
+ }
+ else
+ {
+ const auto& TexFmtInfo = GetTextureFormatAttribs(m_Desc.Format);
+ const auto PixelSize = TexFmtInfo.NumComponents * TexFmtInfo.ComponentSize;
+ VERIFY( (SubresData.Stride % PixelSize)==0, "Data stride is not multiple of pixel size" );
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, SubresData.Stride / PixelSize);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+
+ glTexSubImage2D(m_BindTarget, MipLevel,
+ DstBox.MinX,
+ DstBox.MinY,
+ DstBox.MaxX - DstBox.MinX,
+ DstBox.MaxY - DstBox.MinY,
+ TransferAttribs.PixelFormat, TransferAttribs.DataType,
+ SubresData.pData);
+ }
+ CHECK_GL_ERROR("Failed to update subimage data");
+
+ ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) );
+}
+
+void Texture2D_OGL::AttachToFramebuffer( const TextureViewDesc& ViewDesc, GLenum AttachmentPoint )
+{
+ // For glFramebufferTexture2D(), if texture name is not zero, then texture target must be GL_TEXTURE_2D,
+ // GL_TEXTURE_RECTANGLE or one of the 6 cubemap face targets GL_TEXTURE_CUBE_MAP_POSITIVE_X, ...
+ glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER, AttachmentPoint, m_BindTarget, m_GlTexture, ViewDesc.MostDetailedMip );
+ CHECK_GL_ERROR( "Failed to attach texture 2D to draw framebuffer" );
+ glFramebufferTexture2D( GL_READ_FRAMEBUFFER, AttachmentPoint, m_BindTarget, m_GlTexture, ViewDesc.MostDetailedMip );
+ CHECK_GL_ERROR( "Failed to attach texture 2D to read framebuffer" );
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture3D_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture3D_OGL.cpp
new file mode 100644
index 00000000..03913c3d
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/Texture3D_OGL.cpp
@@ -0,0 +1,171 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "Texture3D_OGL.h"
+#include "RenderDeviceGLImpl.h"
+#include "DeviceContextGLImpl.h"
+#include "GLTypeConversions.h"
+#include "GraphicsUtilities.h"
+
+namespace Diligent
+{
+
+Texture3D_OGL::Texture3D_OGL( class RenderDeviceGLImpl *pDeviceGL,
+ class DeviceContextGLImpl *pDeviceContext,
+ const TextureDesc& TexDesc,
+ const TextureData &InitData /*= TextureData()*/,
+ bool bIsDeviceInternal /*= false*/) :
+ TextureBaseGL(pDeviceGL, TexDesc, InitData, bIsDeviceInternal)
+{
+ auto &ContextState = pDeviceContext->GetContextState();
+
+ m_BindTarget = GL_TEXTURE_3D;
+ ContextState.BindTexture(-1, m_BindTarget, m_GlTexture);
+ // levels format width height depth
+ glTexStorage3D(m_BindTarget, m_Desc.MipLevels, m_GLTexFormat, m_Desc.Width, m_Desc.Height, m_Desc.Depth);
+ CHECK_GL_ERROR_AND_THROW("Failed to allocate storage for the 3D texture");
+ // When target is GL_TEXTURE_3D, calling glTexStorage3D is equivalent to the following pseudo-code:
+ //for (i = 0; i < levels; i++)
+ //{
+ // glTexImage3D(target, i, internalformat, width, height, depth, 0, format, type, NULL);
+ // width = max(1, (width / 2));
+ // height = max(1, (height / 2));
+ // depth = max(1, (depth / 2));
+ //
+
+ SetDefaultGLParameters();
+
+ if( InitData.pSubResources )
+ {
+ if( m_Desc.MipLevels == InitData.NumSubresources )
+ {
+ for(Uint32 Mip = 0; Mip < m_Desc.MipLevels; ++Mip)
+ {
+ Box DstBox(0, std::max(m_Desc.Width >>Mip, 1U),
+ 0, std::max(m_Desc.Height>>Mip, 1U),
+ 0, std::max(m_Desc.Depth >>Mip, 1U));
+ // UpdateData() is a virtual function. If we try to call it through vtbl from here,
+ // we will get into TextureBaseGL::UpdateData(), because instance of Texture3D_OGL
+ // is not fully constructed yet.
+ // To call the required function, we need to explicitly specify the class:
+ Texture3D_OGL::UpdateData( pDeviceContext, Mip, 0, DstBox, InitData.pSubResources[Mip] );
+ }
+ }
+ else
+ {
+ UNEXPECTED("Incorrect number of subresources");
+ }
+ }
+
+ ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) );
+}
+
+Texture3D_OGL::~Texture3D_OGL()
+{
+}
+
+
+void Texture3D_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )
+{
+ TextureBaseGL::UpdateData(pContext, MipLevel, Slice, DstBox, SubresData);
+
+ auto *pDeviceContextGL = ValidatedCast<DeviceContextGLImpl>(pContext);
+ auto &ContextState = pDeviceContextGL->GetContextState();
+
+ // GL_TEXTURE_UPDATE_BARRIER_BIT:
+ // Writes to a texture via glTex( Sub )Image*, glCopyTex( Sub )Image*, glClearTex*Image,
+ // glCompressedTex( Sub )Image*, and reads via glTexImage() after the barrier will reflect
+ // data written by shaders prior to the barrier. Additionally, texture writes from these
+ // commands issued after the barrier will not execute until all shader writes initiated prior
+ // to the barrier complete
+ TextureMemoryBarrier( GL_TEXTURE_UPDATE_BARRIER_BIT, ContextState );
+
+ ContextState.BindTexture(-1, m_BindTarget, m_GlTexture);
+
+ // Transfers to OpenGL memory are called unpack operations
+ // If there is a buffer bound to GL_PIXEL_UNPACK_BUFFER target, then all the pixel transfer
+ // operations will be performed from this buffer. We need to make sure none is bound
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+ auto TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
+
+ const auto TexFmtInfo = GetTextureFormatAttribs(m_Desc.Format);
+ const auto PixelSize = TexFmtInfo.NumComponents * TexFmtInfo.ComponentSize;
+ VERIFY( (SubresData.Stride % PixelSize)==0, "Data stride is not multiple of pixel size" );
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, SubresData.Stride / PixelSize);
+
+ VERIFY( (SubresData.DepthStride % SubresData.Stride)==0, "Depth stride is not multiple of stride" );
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, SubresData.DepthStride / SubresData.Stride);
+
+ glTexSubImage3D(m_BindTarget, MipLevel,
+ DstBox.MinX,
+ DstBox.MinY,
+ DstBox.MinZ,
+ DstBox.MaxX - DstBox.MinX,
+ DstBox.MaxY - DstBox.MinY,
+ DstBox.MaxZ - DstBox.MinZ,
+ TransferAttribs.PixelFormat, TransferAttribs.DataType,
+ SubresData.pData);
+
+ CHECK_GL_ERROR("Failed to update subimage data");
+
+ ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) );
+}
+
+void Texture3D_OGL::AttachToFramebuffer( const TextureViewDesc& ViewDesc, GLenum AttachmentPoint )
+{
+ auto NumDepthSlicesInMip = m_Desc.Depth >> ViewDesc.MostDetailedMip;
+ if( ViewDesc.NumDepthSlices == NumDepthSlicesInMip )
+ {
+ glFramebufferTexture( GL_DRAW_FRAMEBUFFER, AttachmentPoint, m_GlTexture, ViewDesc.MostDetailedMip );
+ CHECK_GL_ERROR( "Failed to attach texture 3D to draw framebuffer" );
+ glFramebufferTexture( GL_READ_FRAMEBUFFER, AttachmentPoint, m_GlTexture, ViewDesc.MostDetailedMip );
+ CHECK_GL_ERROR( "Failed to attach texture 3D to read framebuffer" );
+ }
+ else if( ViewDesc.NumDepthSlices == 1 )
+ {
+ // For glFramebufferTexture3D(), if texture name is not zero, then texture target must be GL_TEXTURE_3D
+ //glFramebufferTexture3D( GL_DRAW_FRAMEBUFFER, AttachmentPoint, m_BindTarget, m_GlTexture, ViewDesc.MostDetailedMip, ViewDesc.FirstDepthSlice );
+ //glFramebufferTexture3D( GL_READ_FRAMEBUFFER, AttachmentPoint, m_BindTarget, m_GlTexture, ViewDesc.MostDetailedMip, ViewDesc.FirstDepthSlice );
+
+ // On Android (at least on Intel HW), glFramebufferTexture3D() runs without errors, but the
+ // FBO turns out to be incomplete. glFramebufferTextureLayer() seems to work fine.
+ glFramebufferTextureLayer( GL_DRAW_FRAMEBUFFER, AttachmentPoint, m_GlTexture, ViewDesc.MostDetailedMip, ViewDesc.FirstDepthSlice );
+ CHECK_GL_ERROR( "Failed to attach texture 3D to draw framebuffer" );
+ glFramebufferTextureLayer( GL_READ_FRAMEBUFFER, AttachmentPoint, m_GlTexture, ViewDesc.MostDetailedMip, ViewDesc.FirstDepthSlice );
+ CHECK_GL_ERROR( "Failed to attach texture 3D to read framebuffer" );
+ }
+ else
+ {
+ UNEXPECTED( "Only one slice or the entire 3D texture can be attached to a framebuffer" );
+ }
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp
new file mode 100644
index 00000000..0e893369
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp
@@ -0,0 +1,433 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "TextureBaseGL.h"
+#include "RenderDeviceGLImpl.h"
+#include "GLTypeConversions.h"
+#include "TextureViewGLImpl.h"
+#include "GLContextState.h"
+#include "DeviceContextGLImpl.h"
+
+namespace Diligent
+{
+
+TextureBaseGL::TextureBaseGL(class RenderDeviceGLImpl *pDeviceGL, const TextureDesc& TexDesc, const TextureData &InitData /*= TextureData()*/, bool bIsDeviceInternal /*= false*/) :
+ TTextureBase( pDeviceGL, TexDesc, bIsDeviceInternal ),
+ m_GlTexture(true), // Create Texture immediately
+ m_BindTarget(0),
+ m_GLTexFormat( TexFormatToGLInternalTexFormat(m_Desc.Format, m_Desc.BindFlags) )
+ //m_uiMapTarget(0)
+{
+ VERIFY( m_GLTexFormat != 0, "Unsupported texture format" );
+ if( TexDesc.Usage == USAGE_STATIC && InitData.pSubResources == nullptr )
+ LOG_ERROR_AND_THROW("Static Texture must be initialized with data at creation time");
+}
+
+TextureBaseGL::~TextureBaseGL()
+{
+ // Release all FBOs that contain current texture
+ // NOTE: we cannot check if BIND_RENDER_TARGET
+ // flag is set, because CopyData() can bind
+ // texture as render target even when no flag
+ // is set
+ static_cast<RenderDeviceGLImpl*>( GetDevice() )->m_FBOCache.OnReleaseTexture(this);
+}
+
+IMPLEMENT_QUERY_INTERFACE( TextureBaseGL, IID_TextureGL, TTextureBase )
+
+
+void TextureBaseGL::CreateViewInternal( const struct TextureViewDesc &OrigViewDesc, class ITextureView **ppView, bool bIsDefaultView )
+{
+ VERIFY( ppView != nullptr, "Null pointer provided" );
+ if( !ppView )return;
+ VERIFY( *ppView == nullptr, "Overwriting reference to existing object may cause memory leaks" );
+
+ *ppView = nullptr;
+
+ try
+ {
+ auto ViewDesc = OrigViewDesc;
+ CorrectTextureViewDesc(ViewDesc);
+
+ // http://www.opengl.org/wiki/Texture_Storage#Texture_views
+
+ GLenum GLViewFormat = TexFormatToGLInternalTexFormat( ViewDesc.Format, m_Desc.BindFlags );
+ VERIFY( GLViewFormat != 0, "Unsupported texture format" );
+
+ TextureViewGLImpl *pViewOGL = nullptr;
+ if( ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE )
+ {
+ bool bIsFullTextureView =
+ ViewDesc.TextureType == m_Desc.Type &&
+ ViewDesc.Format == CorrectTextureViewFormat( m_Desc.Format, ViewDesc.ViewType ) &&
+ ViewDesc.MostDetailedMip == 0 &&
+ ViewDesc.NumMipLevels == m_Desc.MipLevels &&
+ ViewDesc.FirstArraySlice == 0 &&
+ ViewDesc.NumArraySlices == m_Desc.ArraySize;
+
+ pViewOGL = new TextureViewGLImpl( GetDevice(), ViewDesc, this,
+ !bIsFullTextureView, // Create OpenGL texture view object if view
+ // does not address the whole texture
+ bIsDefaultView
+ );
+ if( !bIsFullTextureView )
+ {
+ GLenum GLViewTarget = 0;
+ switch(ViewDesc.TextureType)
+ {
+ case TEXTURE_TYPE_1D:
+ GLViewTarget = GL_TEXTURE_1D;
+ ViewDesc.NumArraySlices = 1;
+ break;
+
+ case TEXTURE_TYPE_1D_ARRAY:
+ GLViewTarget = GL_TEXTURE_1D_ARRAY;
+ break;
+
+ case TEXTURE_TYPE_2D:
+ GLViewTarget = m_Desc.SampleCount > 1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
+ ViewDesc.NumArraySlices = 1;
+ break;
+
+ case TEXTURE_TYPE_2D_ARRAY:
+ GLViewTarget = m_Desc.SampleCount > 1 ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY;
+ break;
+
+ case TEXTURE_TYPE_3D:
+ GLViewTarget = GL_TEXTURE_3D;
+ break;
+
+ default: UNEXPECTED("Unsupported texture view type");
+ }
+
+ glTextureView( pViewOGL->GetHandle(), GLViewTarget, m_GlTexture, GLViewFormat, ViewDesc.MostDetailedMip, ViewDesc.NumMipLevels, ViewDesc.FirstArraySlice, ViewDesc.NumArraySlices );
+ CHECK_GL_ERROR_AND_THROW( "Failed to create texture view" );
+ }
+ }
+ else if( ViewDesc.ViewType == TEXTURE_VIEW_UNORDERED_ACCESS )
+ {
+ VERIFY( ViewDesc.NumArraySlices == 1 || ViewDesc.NumArraySlices == m_Desc.ArraySize,
+ "Only single array/depth slice or the whole texture can be bound as UAV in OpenGL");
+ VERIFY( ViewDesc.AccessFlags != 0, "At least one access flag must be specified" );
+ pViewOGL = new TextureViewGLImpl( GetDevice(), ViewDesc, this,
+ false, // Do NOT create texture view OpenGL object
+ bIsDefaultView
+ );
+ }
+ else if( ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET )
+ {
+ VERIFY( ViewDesc.NumMipLevels == 1, "Only single mip level can be bound as RTV" );
+ pViewOGL = new TextureViewGLImpl( GetDevice(), ViewDesc, this,
+ false, // Do NOT create texture view OpenGL object
+ bIsDefaultView
+ );
+ }
+ else if( ViewDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL )
+ {
+ VERIFY( ViewDesc.NumMipLevels == 1, "Only single mip level can be bound as DSV" );
+ pViewOGL = new TextureViewGLImpl( GetDevice(), ViewDesc, this,
+ false, // Do NOT create texture view OpenGL object
+ bIsDefaultView
+ );
+ }
+
+ if( bIsDefaultView )
+ *ppView = pViewOGL;
+ else
+ {
+ if( pViewOGL )
+ {
+ pViewOGL->QueryInterface( IID_TextureView, reinterpret_cast<IObject**>(ppView) );
+ }
+ }
+ }
+ catch( const std::runtime_error& )
+ {
+ const auto *ViewTypeName = GetTexViewTypeLiteralName(OrigViewDesc.ViewType);
+ LOG_ERROR("Failed to create view \"", OrigViewDesc.Name ? OrigViewDesc.Name : "", "\" (", ViewTypeName, ") for texture \"", m_Desc.Name ? m_Desc.Name : "", "\"" )
+ }
+}
+
+
+void TextureBaseGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )
+{
+ TTextureBase::UpdateData(pContext, MipLevel, Slice, DstBox, SubresData);
+}
+
+//void TextureBaseGL :: UpdateData(Uint32 Offset, Uint32 Size, const PVoid pData)
+//{
+// CTexture::UpdateData(Offset, Size, pData);
+//
+// glBindTexture(GL_ARRAY_Texture, m_GlTexture);
+// glTextureSubData(GL_ARRAY_Texture, Offset, Size, pData);
+// glBindTexture(GL_ARRAY_Texture, 0);
+//}
+//
+
+void TextureBaseGL :: CopyData(IDeviceContext *pContext,
+ ITexture *pSrcTexture,
+ Uint32 SrcMipLevel,
+ Uint32 SrcSlice,
+ const Box *pSrcBox,
+ Uint32 DstMipLevel,
+ Uint32 DstSlice,
+ Uint32 DstX,
+ Uint32 DstY,
+ Uint32 DstZ)
+{
+ auto *pDeviceCtxGL = ValidatedCast<DeviceContextGLImpl>( pContext );
+ auto *pSrcTextureGL = ValidatedCast<TextureBaseGL>( pSrcTexture );
+ const auto& SrcTexDesc = pSrcTextureGL->GetDesc();
+
+ Box SrcBox;
+ if( pSrcBox == nullptr )
+ {
+ SrcBox.MaxX = std::max( SrcTexDesc.Width >> SrcMipLevel, 1u );
+ if( SrcTexDesc.Type == TEXTURE_TYPE_1D ||
+ SrcTexDesc.Type == TEXTURE_TYPE_1D_ARRAY )
+ SrcBox.MaxY = 1;
+ else
+ SrcBox.MaxY = std::max( SrcTexDesc.Height >> SrcMipLevel, 1u );
+
+ if( SrcTexDesc.Type == TEXTURE_TYPE_3D )
+ SrcBox.MaxZ = std::max( SrcTexDesc.Depth >> SrcMipLevel, 1u );
+ else
+ SrcBox.MaxZ = 1;
+ pSrcBox = &SrcBox;
+ }
+
+ TTextureBase::CopyData( pContext, pSrcTexture, SrcMipLevel, SrcSlice, pSrcBox,
+ DstMipLevel, DstSlice, DstX, DstY, DstZ );
+
+ if( glCopyImageSubData )
+ {
+ GLint SrcSliceY = (SrcTexDesc.Type == GL_TEXTURE_1D_ARRAY) ? SrcSlice : 0;
+ GLint SrcSliceZ = (SrcTexDesc.Type == GL_TEXTURE_2D_ARRAY) ? SrcSlice : 0;
+ GLint DstSliceY = (m_Desc.Type == GL_TEXTURE_1D_ARRAY) ? DstSlice : 0;
+ GLint DstSliceZ = (m_Desc.Type == GL_TEXTURE_2D_ARRAY) ? DstSlice : 0;
+ glCopyImageSubData(
+ pSrcTextureGL->GetGLHandle(),
+ pSrcTextureGL->GetBindTarget(),
+ SrcMipLevel,
+ pSrcBox->MinX,
+ pSrcBox->MinY + SrcSliceY,
+ pSrcBox->MinZ + SrcSliceZ, // Slice must be zero for 3D texture
+ GetGLHandle(),
+ GetBindTarget(),
+ DstMipLevel,
+ DstX,
+ DstY + DstSliceY,
+ DstZ + DstSliceZ, // Slice must be zero for 3D texture
+ pSrcBox->MaxX - pSrcBox->MinX,
+ pSrcBox->MaxY - pSrcBox->MinY,
+ pSrcBox->MaxZ - pSrcBox->MinZ );
+ CHECK_GL_ERROR( "glCopyImageSubData() failed" );
+ }
+ else
+ {
+ const auto &FmtAttribs = GetDevice()->GetTextureFormatInfoExt( m_Desc.Format );
+ if( !FmtAttribs.ColorRenderable )
+ {
+ LOG_ERROR_MESSAGE( "Unable to perform copy operation because ", FmtAttribs.Name, " is not color renderable format" );
+ return;
+ }
+
+ auto *pRenderDeviceGL = ValidatedCast<RenderDeviceGLImpl>(GetDevice());
+ auto &FBOCache = pRenderDeviceGL->m_FBOCache;
+ auto &TexRegionRender = pRenderDeviceGL->m_TexRegionRender;
+ TexRegionRender.SetStates(pDeviceCtxGL);
+
+ // Create temporary SRV for the entire source texture
+ TextureViewDesc SRVDesc;
+ SRVDesc.TextureType = SrcTexDesc.Type;
+ SRVDesc.ViewType = TEXTURE_VIEW_SHADER_RESOURCE;
+ CorrectTextureViewDesc( SRVDesc );
+ // Note: texture view allocates memory for the copy of the name
+ // If the name is empty, memory should not be allocated
+ TextureViewGLImpl SRV( GetDevice(), SRVDesc, pSrcTextureGL,
+ false, // Do NOT create texture view OpenGL object
+ true // The view, like default view, should not
+ // keep strong reference to the texture
+ );
+
+ for( Uint32 DepthSlice = 0; DepthSlice < pSrcBox->MaxZ - pSrcBox->MinZ; ++DepthSlice )
+ {
+ // Create temporary RTV for the target subresource
+ TextureViewDesc RTVDesc;
+ RTVDesc.TextureType = m_Desc.Type;
+ RTVDesc.ViewType = TEXTURE_VIEW_RENDER_TARGET;
+ RTVDesc.FirstArraySlice = DepthSlice + DstSlice;
+ RTVDesc.MostDetailedMip = DstMipLevel;
+ RTVDesc.NumArraySlices = 1;
+ CorrectTextureViewDesc( RTVDesc );
+ // Note: texture view allocates memory for the copy of the name
+ // If the name is empty, memory should not be allocated
+ TextureViewGLImpl RTV( GetDevice(), RTVDesc, this,
+ false, // Do NOT create texture view OpenGL object
+ true // The view, like default view, should not
+ // keep strong reference to the texture
+ );
+
+ ITextureView *pRTVs[] = { &RTV };
+ pDeviceCtxGL->SetRenderTargets( _countof( pRTVs ), pRTVs, nullptr );
+
+ Viewport VP;
+ VP.TopLeftX = static_cast<float>( DstX );
+ VP.TopLeftY = static_cast<float>( DstY );
+ VP.Width = static_cast<float>(pSrcBox->MaxX - pSrcBox->MinX);
+ VP.Height = static_cast<float>(pSrcBox->MaxY - pSrcBox->MinY);
+ pDeviceCtxGL->SetViewports( 1, &VP, 0, 0 );
+
+ TexRegionRender.Render( pDeviceCtxGL,
+ &SRV,
+ SrcTexDesc.Type,
+ SrcTexDesc.Format,
+ static_cast<Int32>(pSrcBox->MinX) - static_cast<Int32>(DstX),
+ static_cast<Int32>(pSrcBox->MinY) - static_cast<Int32>(DstY),
+ SrcSlice + pSrcBox->MinZ + DepthSlice,
+ SrcMipLevel );
+ }
+
+ TexRegionRender.RestoreStates(pDeviceCtxGL);
+ }
+}
+
+
+void TextureBaseGL :: Map(IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapFlags, PVoid &pMappedData)
+{
+ TTextureBase::Map( pContext, MapType, MapFlags, pMappedData );
+ //VERIFY( m_uiMapTarget == 0 && "Texture is already mapped");
+
+ //m_uiMapTarget = ( MapType == MAP_READ ) ? GL_COPY_READ_Texture : GL_COPY_WRITE_Texture;
+ //glBindTexture(m_uiMapTarget, m_GlTexture);
+
+ //// !!!WARNING!!! GL_MAP_UNSYNCHRONIZED_BIT is not the same thing as MAP_FLAG_DO_NOT_WAIT.
+ //// If GL_MAP_UNSYNCHRONIZED_BIT flag is set, OpenGL will not attempt to synchronize operations
+ //// on the Texture. This does not mean that map will fail if the Texture still in use. It is thus
+ //// what WRITE_NO_OVERWRITE does
+
+ //GLbitfield Access = 0;
+ //switch(MapType)
+ //{
+ // case MAP_READ:
+ // Access |= GL_MAP_READ_BIT;
+ // break;
+
+ // case MAP_WRITE:
+ // Access |= GL_MAP_WRITE_BIT;
+ // break;
+
+ // case MAP_READ_WRITE:
+ // Access |= GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
+ // break;
+
+ // case MAP_WRITE_DISCARD:
+ // // If GL_MAP_INVALIDATE_Texture_BIT is specified, the entire contents of the Texture may
+ // // be discarded and considered invalid, regardless of the specified range. Any data
+ // // lying outside the mapped range of the Texture object becomes undefined,as does any
+ // // data within the range but not subsequently written by the application.This flag may
+ // // not be used with GL_MAP_READ_BIT.
+ // Access |= GL_MAP_INVALIDATE_Texture_BIT | GL_MAP_WRITE_BIT;
+ // break;
+
+ // case MAP_WRITE_NO_OVERWRITE:
+ // // If GL_MAP_UNSYNCHRONIZED_BIT flag is set, OpenGL will not attempt to synchronize
+ // // operations on the Texture.
+ // Access |= GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
+ // break;
+
+ // default: UNEXPECTED("Unknown map type" );
+ //}
+
+ //pMappedData = glMapTextureRange(m_uiMapTarget, 0, m_Desc.uiSizeInBytes, Access);
+ //VERIFY( "Map failed" && pMappedData );
+ //glBindTexture(m_uiMapTarget, 0);
+}
+
+void TextureBaseGL::Unmap( IDeviceContext *pContext )
+{
+ TTextureBase::Unmap(pContext);
+
+ //glBindTexture(m_uiMapTarget, m_GlTexture);
+ //glUnmapTexture(m_uiMapTarget);
+ //glBindTexture(m_uiMapTarget, 0);
+ //m_uiMapTarget = 0;
+}
+
+void TextureBaseGL::TextureMemoryBarrier( Uint32 RequiredBarriers, GLContextState &GLContextState )
+{
+ const Uint32 TextureBarriers =
+ GL_TEXTURE_FETCH_BARRIER_BIT |
+ GL_SHADER_IMAGE_ACCESS_BARRIER_BIT |
+ GL_PIXEL_BUFFER_BARRIER_BIT |
+ GL_TEXTURE_UPDATE_BARRIER_BIT |
+ GL_FRAMEBUFFER_BARRIER_BIT;
+ VERIFY( (RequiredBarriers & TextureBarriers) != 0, "At least one texture memory barrier flag should be set" );
+ VERIFY( (RequiredBarriers & ~TextureBarriers) == 0, "Inappropriate texture memory barrier flag" );
+
+ GLContextState.EnsureMemoryBarrier( RequiredBarriers, this );
+}
+
+void TextureBaseGL::SetDefaultGLParameters()
+{
+#ifdef _DEBUG
+ GLint BoundTex;
+ GLint TextureBinding = 0;
+ switch( m_BindTarget )
+ {
+ case GL_TEXTURE_1D: TextureBinding = GL_TEXTURE_BINDING_1D; break;
+ case GL_TEXTURE_1D_ARRAY: TextureBinding = GL_TEXTURE_BINDING_1D_ARRAY; break;
+ case GL_TEXTURE_2D: TextureBinding = GL_TEXTURE_BINDING_2D; break;
+ case GL_TEXTURE_2D_ARRAY: TextureBinding = GL_TEXTURE_BINDING_2D_ARRAY; break;
+ case GL_TEXTURE_2D_MULTISAMPLE: TextureBinding = GL_TEXTURE_BINDING_2D_MULTISAMPLE; break;
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: TextureBinding = GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY; break;
+ case GL_TEXTURE_3D: TextureBinding = GL_TEXTURE_BINDING_3D; break;
+ default: UNEXPECTED("Unknown bind target");
+ }
+ glGetIntegerv( TextureBinding, &BoundTex );
+ CHECK_GL_ERROR( "Failed to set GL_TEXTURE_MIN_FILTER texture parameter" );
+ VERIFY( BoundTex == m_GlTexture, "Current texture is not bound to GL context" );
+#endif
+
+ if( m_BindTarget != GL_TEXTURE_2D_MULTISAMPLE &&
+ m_BindTarget != GL_TEXTURE_2D_MULTISAMPLE_ARRAY )
+ {
+ // Note that texture bound to image unit must be complete.
+ // That means that if an integer texture is being bound, its
+ // GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER must be NEAREST,
+ // otherwise it will be incomplete
+
+ // The default value of GL_TEXTURE_MIN_FILTER is GL_NEAREST_MIPMAP_LINEAR
+ // Reset it to GL_NEAREST to avoid incompletness issues with integer textures
+ glTexParameteri( m_BindTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ CHECK_GL_ERROR( "Failed to set GL_TEXTURE_MIN_FILTER texture parameter" );
+
+ // The default value of GL_TEXTURE_MAG_FILTER is GL_LINEAR
+ glTexParameteri( m_BindTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+ CHECK_GL_ERROR( "Failed to set GL_TEXTURE_MAG_FILTER texture parameter" );
+ }
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/TextureViewGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureViewGLImpl.cpp
new file mode 100644
index 00000000..10fbb630
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/TextureViewGLImpl.cpp
@@ -0,0 +1,84 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "TextureViewGLImpl.h"
+#include "RenderDeviceGLImpl.h"
+#include "TextureBaseGL.h"
+#include "DeviceContextGLImpl.h"
+
+namespace Diligent
+{
+ TextureViewGLImpl::TextureViewGLImpl( IRenderDevice *pDevice,
+ const TextureViewDesc& ViewDesc,
+ TextureBaseGL* pTexture,
+ bool bCreateGLViewTex,
+ bool bIsDefaultView ) :
+ TTextureViewBase(pDevice, ViewDesc, pTexture, bIsDefaultView),
+ m_ViewTexGLHandle( bCreateGLViewTex ),
+ m_ViewTexBindTarget(0)
+ {
+ }
+
+ TextureViewGLImpl::~TextureViewGLImpl()
+ {
+ }
+
+ IMPLEMENT_QUERY_INTERFACE( TextureViewGLImpl, IID_TextureViewGL, TTextureViewBase )
+
+ const GLObjectWrappers::GLTextureObj& TextureViewGLImpl::GetHandle()
+ {
+ if( m_ViewTexGLHandle )
+ return m_ViewTexGLHandle;
+ else
+ {
+ auto *pTexture = GetTexture();
+ CHECK_DYNAMIC_TYPE( TextureBaseGL, pTexture );
+ return static_cast<TextureBaseGL*>(pTexture)->GetGLHandle();
+ }
+ }
+
+ GLenum TextureViewGLImpl::GetBindTarget()
+ {
+ if( m_ViewTexGLHandle )
+ return m_ViewTexBindTarget;
+ else
+ {
+ auto *pTexture = GetTexture();
+ CHECK_DYNAMIC_TYPE( TextureBaseGL, pTexture );
+ return static_cast<TextureBaseGL*>(pTexture)->GetBindTarget();
+ }
+ }
+
+ void TextureViewGLImpl::GenerateMips( IDeviceContext *pContext )
+ {
+ auto pCtxGL = ValidatedCast<DeviceContextGLImpl>( pContext );
+ auto &GLState = pCtxGL->GetContextState();
+ auto BindTarget = GetBindTarget();
+ GLState.BindTexture( -1, BindTarget, GetHandle() );
+ glGenerateMipmap( BindTarget );
+ CHECK_GL_ERROR( "Failed to generate mip maps" );
+ GLState.BindTexture( -1, BindTarget, GLObjectWrappers::GLTextureObj(false) );
+ }
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp b/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp
new file mode 100644
index 00000000..4a3891b3
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp
@@ -0,0 +1,220 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "VAOCache.h"
+#include "RenderDeviceGLImpl.h"
+#include "GLObjectWrapper.h"
+#include "BufferGLImpl.h"
+#include "GLTypeConversions.h"
+#include "GLContextState.h"
+
+namespace Diligent
+{
+
+VAOCache::VAOCache()
+{
+ m_Cache.max_load_factor(0.5f);
+ m_VertexDescToKey.max_load_factor(0.5f);
+ m_BuffToKey.max_load_factor(0.5f);
+}
+
+VAOCache::~VAOCache()
+{
+ VERIFY(m_Cache.empty(), "VAO cache is not empty. Are there any unreleased objects?");
+ VERIFY(m_VertexDescToKey.empty(), "VertexDescToKey hash is not empty" );
+ VERIFY(m_BuffToKey.empty(), "BuffToKey hash is not empty");
+}
+
+void VAOCache::OnDestroyBuffer(IBuffer *pBuffer)
+{
+ ThreadingTools::LockHelper CacheLock(m_CacheLockFlag);
+ auto EqualRange = m_BuffToKey.equal_range(pBuffer);
+ for(auto It = EqualRange.first; It != EqualRange.second; ++It)
+ {
+ m_Cache.erase(It->second);
+ }
+ m_BuffToKey.erase(EqualRange.first, EqualRange.second);
+}
+
+void VAOCache::OnDestroyVertexDesc(IVertexDescription *pVertexDesc)
+{
+ ThreadingTools::LockHelper CacheLock(m_CacheLockFlag);
+ auto EqualRange = m_VertexDescToKey.equal_range(pVertexDesc);
+ for(auto It = EqualRange.first; It != EqualRange.second; ++It)
+ {
+ m_Cache.erase(It->second);
+ }
+ m_VertexDescToKey.erase(EqualRange.first, EqualRange.second);
+}
+
+const GLObjectWrappers::GLVertexArrayObj& VAOCache::GetVAO( IVertexDescription &VertexDesc,
+ IBuffer *pIndexBuffer,
+ vector< VertexStreamInfo > &VertexStreams,
+ GLContextState &GLContextState )
+{
+ // Lock the cache
+ ThreadingTools::LockHelper CacheLock(m_CacheLockFlag);
+
+ RefCntAutoPtr<IBuffer> spVertexBuffers[MaxBufferSlots];
+
+ // Get layout
+ const auto *LayoutElems = VertexDesc.GetDesc().LayoutElements;
+ auto NumElems = VertexDesc.GetDesc().NumElements;
+ const auto *TightStrides = VertexDesc.GetTightStrides();
+ // Construct the key
+ VAOCacheKey Key = {0};
+ Key.pVertexDesc = &VertexDesc;
+ Key.pIndexBuffer = pIndexBuffer;
+
+ auto LayoutIt = LayoutElems;
+ for( size_t Elem = 0; Elem < NumElems; ++Elem, ++LayoutIt )
+ {
+ auto BuffSlot = LayoutIt->BufferSlot;
+ if( BuffSlot >= VertexStreams.size() )
+ {
+ UNEXPECTED( "Input layout requires more buffers than bound to the pipeline" );
+ continue;
+ }
+ if( BuffSlot >= MaxBufferSlots )
+ {
+ VERIFY( BuffSlot >= MaxBufferSlots, "Incorrect input slot" );
+ continue;
+ }
+ auto &CurrStream = VertexStreams[BuffSlot];
+ auto Stride = CurrStream.Stride ? CurrStream.Stride : TightStrides[BuffSlot];
+ auto &spCurrBuf = spVertexBuffers[BuffSlot];
+ auto &CurrStreamKey = Key.Streams[BuffSlot];
+ if( !spCurrBuf )
+ {
+ spCurrBuf = CurrStream.pBuffer;
+ VERIFY( spCurrBuf, "Buffer no longer exists" );
+
+ CHECK_DYNAMIC_TYPE( BufferGLImpl, spCurrBuf.RawPtr() );
+ static_cast<BufferGLImpl*>(spCurrBuf.RawPtr())->BufferMemoryBarrier(
+ GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT,// Vertex data sourced from buffer objects after the barrier
+ // will reflect data written by shaders prior to the barrier.
+ // The set of buffer objects affected by this bit is derived
+ // from the GL_VERTEX_ARRAY_BUFFER_BINDING bindings
+ GLContextState);
+
+ CurrStreamKey.pBuffer = spCurrBuf.RawPtr();
+ CurrStreamKey.Stride = Stride;
+ CurrStreamKey.Offset = CurrStream.Offset;
+ }
+ else
+ {
+ VERIFY( spCurrBuf == CurrStream.pBuffer, "Buffer no longer exists" );
+ VERIFY( CurrStreamKey.pBuffer == spCurrBuf.RawPtr(), "Unexpected buffer" );
+ VERIFY( CurrStreamKey.Stride == Stride, "Unexpected buffer stride" );
+ VERIFY( CurrStreamKey.Offset == CurrStream.Offset, "Unexpected buffer offset" );
+ }
+ }
+
+ if( pIndexBuffer )
+ {
+ CHECK_DYNAMIC_TYPE( BufferGLImpl, pIndexBuffer );
+ static_cast<BufferGLImpl*>(pIndexBuffer)->BufferMemoryBarrier(
+ GL_ELEMENT_ARRAY_BARRIER_BIT,// Vertex array indices sourced from buffer objects after the barrier
+ // will reflect data written by shaders prior to the barrier.
+ // The buffer objects affected by this bit are derived from the
+ // ELEMENT_ARRAY_BUFFER binding.
+ GLContextState);
+ }
+
+ // Try to find VAO in the map
+ auto It = m_Cache.find(Key);
+ if( It != m_Cache.end() )
+ {
+ return It->second;
+ }
+ else
+ {
+ // Create new VAO
+ GLObjectWrappers::GLVertexArrayObj NewVAO(true);
+
+ // Initialize VAO
+ GLContextState.BindVAO( NewVAO );
+ auto LayoutIt = LayoutElems;
+ for( size_t Elem = 0; Elem < NumElems; ++Elem, ++LayoutIt )
+ {
+ auto BuffSlot = LayoutIt->BufferSlot;
+ if( BuffSlot >= VertexStreams.size() || BuffSlot >= MaxBufferSlots )
+ {
+ UNEXPECTED( "Incorrect input buffer slot" );
+ continue;
+ }
+ // Get buffer through the strong reference. Note that we are not
+ // using pointers stored in the key for safety
+ auto &CurrStream = VertexStreams[BuffSlot];
+ auto Stride = CurrStream.Stride ? CurrStream.Stride : TightStrides[BuffSlot];
+ auto &spBuff = spVertexBuffers[BuffSlot];
+ VERIFY( spBuff, "Vertex buffer is null" );
+ const BufferGLImpl *pBufferOGL = static_cast<const BufferGLImpl*>( spBuff.RawPtr() );
+
+ glBindBuffer(GL_ARRAY_BUFFER, pBufferOGL->m_GlBuffer);
+ GLvoid* DataStartOffset = reinterpret_cast<GLvoid*>( static_cast<size_t>( CurrStream.Offset + LayoutIt->RelativeOffset ) );
+ auto GlType = TypeToGLType(LayoutIt->ValueType);
+ if( !LayoutIt->IsNormalized &&
+ (LayoutIt->ValueType == VT_INT8 ||
+ LayoutIt->ValueType == VT_INT16 ||
+ LayoutIt->ValueType == VT_INT32 ||
+ LayoutIt->ValueType == VT_UINT8 ||
+ LayoutIt->ValueType == VT_UINT16||
+ LayoutIt->ValueType == VT_UINT32 ) )
+ glVertexAttribIPointer(LayoutIt->InputIndex, LayoutIt->NumComponents, GlType, Stride, DataStartOffset );
+ else
+ glVertexAttribPointer(LayoutIt->InputIndex, LayoutIt->NumComponents, GlType, LayoutIt->IsNormalized, Stride, DataStartOffset );
+
+ if( LayoutIt->Frequency == LayoutElement::FREQUENCY_PER_INSTANCE )
+ {
+ // If divisor is zero, then the attribute acts like normal, being indexed by the array or index
+ // buffer. If divisor is non-zero, then the current instance is divided by this divisor, and
+ // the result of that is used to access the attribute array.
+ glVertexAttribDivisor(LayoutIt->InputIndex, LayoutIt->InstanceDataStepRate);
+ }
+ glEnableVertexAttribArray(LayoutIt->InputIndex);
+ }
+ if( pIndexBuffer )
+ {
+ const BufferGLImpl *pIndBufferOGL = static_cast<const BufferGLImpl*>( pIndexBuffer );
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pIndBufferOGL->m_GlBuffer);
+ }
+
+ auto NewElems = m_Cache.emplace( make_pair(Key, std::move(NewVAO)) );
+ // New element must be actually inserted
+ VERIFY( NewElems.second, "New element was not inserted into the cache" );
+ m_VertexDescToKey.insert( make_pair(Key.pVertexDesc, Key) );
+ for(int iStream = 0; iStream < _countof(Key.Streams); ++iStream)
+ {
+ auto *pCurrBuff = Key.Streams[iStream].pBuffer;
+ if( pCurrBuff )
+ m_BuffToKey.insert( make_pair(pCurrBuff, Key) );
+ }
+
+ return NewElems.first->second;
+ }
+}
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/VertexDescGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/VertexDescGLImpl.cpp
new file mode 100644
index 00000000..0b2b6b50
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/VertexDescGLImpl.cpp
@@ -0,0 +1,45 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "VertexDescGLImpl.h"
+#include "RenderDeviceGLImpl.h"
+
+namespace Diligent
+{
+
+VertexDescGLImpl::VertexDescGLImpl( RenderDeviceGLImpl *pDeviceGL, const LayoutDesc &LayoutDesc, bool bIsDeviceInternal ) :
+ TVertexDescriptionBase(pDeviceGL, LayoutDesc)
+{
+
+}
+
+VertexDescGLImpl::~VertexDescGLImpl()
+{
+ static_cast<RenderDeviceGLImpl*>( GetDevice() )->m_VAOCache.OnDestroyVertexDesc(this);
+}
+
+IMPLEMENT_QUERY_INTERFACE( VertexDescGLImpl, IID_VertexDescriptionGL, TVertexDescriptionBase )
+
+}
diff --git a/Graphics/GraphicsEngineOpenGL/src/pch.cpp b/Graphics/GraphicsEngineOpenGL/src/pch.cpp
new file mode 100644
index 00000000..0bfe300d
--- /dev/null
+++ b/Graphics/GraphicsEngineOpenGL/src/pch.cpp
@@ -0,0 +1,31 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+// stdafx.cpp : source file that includes just the standard includes
+// GraphicsEngineOpenGL.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "pch.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file