diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2015-10-21 03:46:28 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2015-10-21 03:46:28 +0000 |
| commit | 9ccee73baca0fd7ecb95c90cb983133b737c6c55 (patch) | |
| tree | 66fea1e6521df31727431520fe3c1ead1896bc5d /Graphics/GraphicsEngineOpenGL | |
| download | DiligentCore-9ccee73baca0fd7ecb95c90cb983133b737c6c55.tar.gz DiligentCore-9ccee73baca0fd7ecb95c90cb983133b737c6c55.zip | |
Release v1.0.0
Diffstat (limited to 'Graphics/GraphicsEngineOpenGL')
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, ¶ms ); + 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 |
