From 8e24a0919d30f939140e776bc5e64bd77767e99c Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Sun, 12 Nov 2017 18:54:50 -0800 Subject: Updated to Diligent Engine 2.1 --- .../build/Win32/GraphicsEngineOpenGL.props | 2 +- .../build/Win32/GraphicsEngineOpenGL.vcxproj | 39 +- .../Win32/GraphicsEngineOpenGL.vcxproj.filters | 15 +- .../build/Win32/jni/Android.mk | 26 +- .../build/Win32/jni/Application.mk | 2 +- .../GraphicsEngineOpenGL/include/BufferGLImpl.h | 27 +- .../include/BufferViewGLImpl.h | 19 +- .../include/DeviceContextGLImpl.h | 9 +- Graphics/GraphicsEngineOpenGL/include/FBOCache.h | 5 + Graphics/GraphicsEngineOpenGL/include/GLContext.h | 32 + .../include/GLContextAndroid.h | 31 +- .../GraphicsEngineOpenGL/include/GLContextState.h | 128 +- .../include/GLContextWindows.h | 6 +- .../GraphicsEngineOpenGL/include/GLObjectWrapper.h | 54 +- .../GraphicsEngineOpenGL/include/GLSLDefinitions.h | 957 ------ .../include/GLSLDefinitions_inc.h | 957 ------ Graphics/GraphicsEngineOpenGL/include/GLStubs.h | 264 +- .../include/GLTypeConversions.h | 1 + .../include/HLSL2GLSLConverter.h | 424 --- .../include/PipelineStateGLImpl.h | 13 +- .../include/RenderDeviceGLESImpl.h | 2 +- .../include/RenderDeviceGLImpl.h | 50 +- .../GraphicsEngineOpenGL/include/SamplerGLImpl.h | 6 +- .../GraphicsEngineOpenGL/include/ShaderGLImpl.h | 6 +- .../include/ShaderResourceBindingGLImpl.h | 6 +- .../GraphicsEngineOpenGL/include/SwapChainGLImpl.h | 6 +- .../GraphicsEngineOpenGL/include/TexRegionRender.h | 8 +- .../include/Texture1DArray_OGL.h | 18 +- .../GraphicsEngineOpenGL/include/Texture1D_OGL.h | 18 +- .../include/Texture2DArray_OGL.h | 18 +- .../GraphicsEngineOpenGL/include/Texture2D_OGL.h | 18 +- .../GraphicsEngineOpenGL/include/Texture3D_OGL.h | 18 +- .../GraphicsEngineOpenGL/include/TextureBaseGL.h | 25 +- .../include/TextureCubeArray_OGL.h | 18 +- .../GraphicsEngineOpenGL/include/TextureCube_OGL.h | 18 +- .../include/TextureViewGLImpl.h | 7 +- Graphics/GraphicsEngineOpenGL/include/VAOCache.h | 79 +- Graphics/GraphicsEngineOpenGL/include/pch.h | 6 +- .../interface/BaseInterfacesGL.h | 8 +- Graphics/GraphicsEngineOpenGL/interface/BufferGL.h | 3 +- .../interface/DeviceContextGL.h | 10 +- .../interface/RenderDeviceFactoryOpenGL.h | 51 +- .../interface/RenderDeviceGL.h | 30 +- .../interface/RenderDeviceGLES.h | 4 +- .../GraphicsEngineOpenGL/interface/TextureGL.h | 6 +- Graphics/GraphicsEngineOpenGL/readme.md | 112 + Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp | 170 +- .../GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp | 9 +- .../src/DeviceContextGLImpl.cpp | 112 +- Graphics/GraphicsEngineOpenGL/src/FBOCache.cpp | 18 +- .../GraphicsEngineOpenGL/src/GLContextAndroid.cpp | 89 +- .../GraphicsEngineOpenGL/src/GLContextState.cpp | 108 +- .../GraphicsEngineOpenGL/src/GLContextWindows.cpp | 66 +- .../src/GLProgramResources.cpp | 15 +- Graphics/GraphicsEngineOpenGL/src/GLStubs.cpp | 19 +- .../GraphicsEngineOpenGL/src/GLTypeConversions.cpp | 311 +- .../src/GraphicsEngineOpenGL.def | 2 +- .../src/HLSL2GLSLConverter.cpp | 3261 -------------------- .../src/PipelineStateGLImpl.cpp | 50 +- .../src/RenderDeviceFactoryOpenGL.cpp | 126 +- .../src/RenderDeviceGLESImpl.cpp | 4 +- .../src/RenderDeviceGLImpl.cpp | 157 +- .../GraphicsEngineOpenGL/src/SamplerGLImpl.cpp | 4 +- Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp | 55 +- .../src/ShaderResourceBindingGLImpl.cpp | 4 +- .../GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp | 4 +- .../GraphicsEngineOpenGL/src/TexRegionRender.cpp | 12 +- .../src/Texture1DArray_OGL.cpp | 39 +- .../GraphicsEngineOpenGL/src/Texture1D_OGL.cpp | 37 +- .../src/Texture2DArray_OGL.cpp | 40 +- .../GraphicsEngineOpenGL/src/Texture2D_OGL.cpp | 38 +- .../GraphicsEngineOpenGL/src/Texture3D_OGL.cpp | 38 +- .../GraphicsEngineOpenGL/src/TextureBaseGL.cpp | 196 +- .../src/TextureCubeArray_OGL.cpp | 37 +- .../GraphicsEngineOpenGL/src/TextureCube_OGL.cpp | 33 +- .../GraphicsEngineOpenGL/src/TextureViewGLImpl.cpp | 4 +- Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp | 119 +- 77 files changed, 2065 insertions(+), 6674 deletions(-) create mode 100644 Graphics/GraphicsEngineOpenGL/include/GLContext.h delete mode 100644 Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions.h delete mode 100644 Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions_inc.h delete mode 100644 Graphics/GraphicsEngineOpenGL/include/HLSL2GLSLConverter.h create mode 100644 Graphics/GraphicsEngineOpenGL/readme.md delete mode 100644 Graphics/GraphicsEngineOpenGL/src/HLSL2GLSLConverter.cpp (limited to 'Graphics/GraphicsEngineOpenGL') diff --git a/Graphics/GraphicsEngineOpenGL/build/Win32/GraphicsEngineOpenGL.props b/Graphics/GraphicsEngineOpenGL/build/Win32/GraphicsEngineOpenGL.props index 783f8a0f..a7fdcf18 100644 --- a/Graphics/GraphicsEngineOpenGL/build/Win32/GraphicsEngineOpenGL.props +++ b/Graphics/GraphicsEngineOpenGL/build/Win32/GraphicsEngineOpenGL.props @@ -3,7 +3,7 @@ - $(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) + $(GraphicsRoot)\GraphicsEngineOpenGL\include;$(GraphicsRoot)\GraphicsEngineOpenGL\interface;$(GraphicsRoot)\GraphicsEngine\include;$(GraphicsRoot)\GraphicsEngine\interface;$(GraphicsRoot)\HLSL2GLSLConverterLib\include;$(GraphicsRoot)\HLSL2GLSLConverterLib\interface;$(GraphicsRoot)\GraphicsTools\include;$(EngineRoot)\Common\include;$(EngineRoot)\Common\interface;$(EngineRoot)\External\glew\include\GL;$(EngineRoot)\Platforms\interface;$(VC_IncludePath);$(WindowsSDK_IncludePath) diff --git a/Graphics/GraphicsEngineOpenGL/build/Win32/GraphicsEngineOpenGL.vcxproj b/Graphics/GraphicsEngineOpenGL/build/Win32/GraphicsEngineOpenGL.vcxproj index 41216527..3976dab7 100644 --- a/Graphics/GraphicsEngineOpenGL/build/Win32/GraphicsEngineOpenGL.vcxproj +++ b/Graphics/GraphicsEngineOpenGL/build/Win32/GraphicsEngineOpenGL.vcxproj @@ -214,7 +214,6 @@ - Level3 Disabled WIN32;_LIB;%(PreprocessorDefinitions) @@ -225,7 +224,6 @@ - Level3 Disabled WIN32;_LIB;%(PreprocessorDefinitions) @@ -238,7 +236,6 @@ - Level3 Disabled WIN32;_LIB;%(PreprocessorDefinitions) @@ -252,7 +249,6 @@ - Level3 Disabled WIN32;_LIB;%(PreprocessorDefinitions) @@ -268,11 +264,11 @@ - Level3 MaxSpeed true true WIN32;_LIB;%(PreprocessorDefinitions) + 4100;4505;4189 Windows @@ -283,11 +279,11 @@ - Level3 MaxSpeed true true WIN32;_LIB;%(PreprocessorDefinitions) + 4100;4505;4189 Windows @@ -300,11 +296,11 @@ - Level3 MaxSpeed true true WIN32;_LIB;%(PreprocessorDefinitions) + 4100;4505;4189 Windows @@ -318,11 +314,11 @@ - Level3 MaxSpeed true true WIN32;_LIB;%(PreprocessorDefinitions) + 4100;4505;4189 Windows @@ -341,33 +337,15 @@ + - - "$(EngineRoot)\Utilities\File2Include\File2String.exe" "%(FullPath)" "$(ProjectRoot)\include\%(Filename)_inc.h" - $(ProjectRoot)\include\%(Filename)_inc.h - "$(EngineRoot)\Utilities\File2Include\File2String.exe" "%(FullPath)" "$(ProjectRoot)\include\%(Filename)_inc.h" - $(ProjectRoot)\include\%(Filename)_inc.h - "$(EngineRoot)\Utilities\File2Include\File2String.exe" "%(FullPath)" "$(ProjectRoot)\include\%(Filename)_inc.h" - $(ProjectRoot)\include\%(Filename)_inc.h - "$(EngineRoot)\Utilities\File2Include\File2String.exe" "%(FullPath)" "$(ProjectRoot)\include\%(Filename)_inc.h" - $(ProjectRoot)\include\%(Filename)_inc.h - "$(EngineRoot)\Utilities\File2Include\File2String.exe" "%(FullPath)" "$(ProjectRoot)\include\%(Filename)_inc.h" - $(ProjectRoot)\include\%(Filename)_inc.h - "$(EngineRoot)\Utilities\File2Include\File2String.exe" "%(FullPath)" "$(ProjectRoot)\include\%(Filename)_inc.h" - $(ProjectRoot)\include\%(Filename)_inc.h - "$(EngineRoot)\Utilities\File2Include\File2String.exe" "%(FullPath)" "$(ProjectRoot)\include\%(Filename)_inc.h" - $(ProjectRoot)\include\%(Filename)_inc.h - "$(EngineRoot)\Utilities\File2Include\File2String.exe" "%(FullPath)" "$(ProjectRoot)\include\%(Filename)_inc.h" - $(ProjectRoot)\include\%(Filename)_inc.h - - @@ -449,7 +427,6 @@ true - @@ -490,6 +467,7 @@ + @@ -498,7 +476,7 @@ {7380f7e6-315f-4b4e-92eb-e6aeee865298} - + {664e6f0d-6784-4760-9565-d54f8eb1edf4} @@ -513,6 +491,9 @@ {c6014499-0cf2-43ec-a773-a4e354fb2d74} + + {1a782154-a5bd-4a05-b837-efc77f126c84} + diff --git a/Graphics/GraphicsEngineOpenGL/build/Win32/GraphicsEngineOpenGL.vcxproj.filters b/Graphics/GraphicsEngineOpenGL/build/Win32/GraphicsEngineOpenGL.vcxproj.filters index cac09c45..db925dc8 100644 --- a/Graphics/GraphicsEngineOpenGL/build/Win32/GraphicsEngineOpenGL.vcxproj.filters +++ b/Graphics/GraphicsEngineOpenGL/build/Win32/GraphicsEngineOpenGL.vcxproj.filters @@ -149,9 +149,6 @@ Header Files - - Header Files - Header Files @@ -176,6 +173,9 @@ Header Files + + Header Files + @@ -259,9 +259,6 @@ Source Files - - Source Files - Source Files @@ -291,11 +288,7 @@ Source Files - - - - Header Files - + diff --git a/Graphics/GraphicsEngineOpenGL/build/Win32/jni/Android.mk b/Graphics/GraphicsEngineOpenGL/build/Win32/jni/Android.mk index fd7b718a..64b2c110 100644 --- a/Graphics/GraphicsEngineOpenGL/build/Win32/jni/Android.mk +++ b/Graphics/GraphicsEngineOpenGL/build/Win32/jni/Android.mk @@ -8,9 +8,10 @@ include $(CLEAR_VARS) # Project configuration LOCAL_MODULE := GraphicsEngineOpenGL -LOCAL_CFLAGS := -std=c++11 -DUSE_GL3_STUB=1 -DENGINE_DLL -DBUILDING_DLL -fvisibility=hidden +LOCAL_CFLAGS := -std=c++11 -DUSE_GL3_STUB=0 -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 +LOCAL_STATIC_LIBRARIES += GraphicsEngine-prebuilt HLSL2GLSLConverterLib-prebuilt AndroidPlatform-prebuilt BasicPlatform-prebuilt GraphicsTools-prebuilt Common-prebuilt +LOCAL_LDLIBS := -lGLESv3 -lEGL -llog -landroid # Include paths PROJECT_ROOT := $(LOCAL_PATH)/../../.. @@ -19,15 +20,23 @@ LOCAL_C_INCLUDES := $(PROJECT_ROOT)/include $(PROJECT_ROOT)/interface $(SOLUTION # Source files #VisualGDBAndroid: AutoUpdateSourcesInNextLine -LOCAL_SRC_FILES := ../../../src/BufferGLImpl.cpp ../../../src/BufferViewGLImpl.cpp ../../../src/DeviceContextGLImpl.cpp ../../../src/DLLMain.cpp ../../../src/FBOCache.cpp ../../../src/GLContextAndroid.cpp ../../../src/GLContextState.cpp ../../../src/GLContextWindows.cpp ../../../src/GLObjectWrapper.cpp ../../../src/GLProgram.cpp ../../../src/GLProgramResources.cpp ../../../src/GLStubs.cpp ../../../src/GLTypeConversions.cpp ../../../src/HLSL2GLSLConverter.cpp ../../../src/PipelineStateGLImpl.cpp ../../../src/RenderDeviceGLImpl.cpp ../../../src/RenderDeviceGLESImpl.cpp ../../../src/SamplerGLImpl.cpp ../../../src/ShaderResourceBindingGLImpl.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/TextureCubeArray_OGL.cpp ../../../src/TextureCube_OGL.cpp ../../../src/TextureViewGLImpl.cpp ../../../src/VAOCache.cpp ../../../src/RenderDeviceFactoryOpenGL.cpp ../../../src/ShaderGLImpl.cpp ../../../src/pch.cpp +LOCAL_SRC_FILES := ../../../src/BufferGLImpl.cpp ../../../src/BufferViewGLImpl.cpp ../../../src/DeviceContextGLImpl.cpp ../../../src/DLLMain.cpp ../../../src/FBOCache.cpp ../../../src/GLContextAndroid.cpp ../../../src/GLContextState.cpp ../../../src/GLContextWindows.cpp ../../../src/GLObjectWrapper.cpp ../../../src/GLProgram.cpp ../../../src/GLProgramResources.cpp ../../../src/GLStubs.cpp ../../../src/GLTypeConversions.cpp ../../../src/PipelineStateGLImpl.cpp ../../../src/RenderDeviceGLImpl.cpp ../../../src/RenderDeviceGLESImpl.cpp ../../../src/SamplerGLImpl.cpp ../../../src/ShaderResourceBindingGLImpl.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/TextureCubeArray_OGL.cpp ../../../src/TextureCube_OGL.cpp ../../../src/TextureViewGLImpl.cpp ../../../src/VAOCache.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) + +LOCAL_MODULE := GraphicsEngineOpenGL_static +LOCAL_MODULE_FILENAME := libGraphicsEngineOpenGL +LOCAL_CFLAGS := -std=c++11 -DUSE_GL3_STUB=0 +LOCAL_LDLIBS := +include $(BUILD_STATIC_LIBRARY) + + + include $(CLEAR_VARS) # Declare pre-built Common library LOCAL_MODULE := Common-prebuilt @@ -49,7 +58,6 @@ LOCAL_MODULE := BasicPlatform-prebuilt LOCAL_SRC_FILES := $(SOLUTION_ROOT)/Platforms/Basic/build/Win32/obj/local/$(TARGET_ARCH_ABI)/libBasicPlatform.a include $(PREBUILT_STATIC_LIBRARY) - include $(CLEAR_VARS) # Declare pre-built GraphicsEngine library LOCAL_MODULE := GraphicsEngine-prebuilt @@ -64,5 +72,9 @@ LOCAL_SRC_FILES := $(SOLUTION_ROOT)/Graphics/GraphicsTools/build/Win32/obj/local 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) +include $(CLEAR_VARS) +# Declare pre-built HLSL2GLSLConverterLib library +LOCAL_MODULE := HLSL2GLSLConverterLib-prebuilt +LOCAL_SRC_FILES := $(SOLUTION_ROOT)/Graphics/HLSL2GLSLConverterLib/build/Win32/obj/local/$(TARGET_ARCH_ABI)/libHLSL2GLSLConverterLib.a +LOCAL_EXPORT_C_INCLUDES := $(SOLUTION_ROOT)/Graphics/HLSL2GLSLConverterLib/include $(SOLUTION_ROOT)/Graphics/HLSL2GLSLConverterLib/interface +include $(PREBUILT_STATIC_LIBRARY) diff --git a/Graphics/GraphicsEngineOpenGL/build/Win32/jni/Application.mk b/Graphics/GraphicsEngineOpenGL/build/Win32/jni/Application.mk index c7e241e8..4147fd50 100644 --- a/Graphics/GraphicsEngineOpenGL/build/Win32/jni/Application.mk +++ b/Graphics/GraphicsEngineOpenGL/build/Win32/jni/Application.mk @@ -4,4 +4,4 @@ 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 +APP_MODULES := GraphicsEngineOpenGL GraphicsEngineOpenGL_static \ No newline at end of file diff --git a/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h index 9055e87f..9d29219f 100644 --- a/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h @@ -37,17 +37,23 @@ namespace Diligent class FixedBlockMemoryAllocator; /// Implementation of the Diligent::IBufferGL interface -class BufferGLImpl : public BufferBase, public AsyncWritableResource +class BufferGLImpl : public BufferBase, public AsyncWritableResource { public: - typedef BufferBase TBufferBase; + typedef BufferBase TBufferBase; - BufferGLImpl(FixedBlockMemoryAllocator &BufferObjMemAllocator, + BufferGLImpl(IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator &BuffViewObjMemAllocator, class RenderDeviceGLImpl *pDeviceGL, const BufferDesc& BuffDesc, - const BufferData &BuffData = BufferData(), - bool IsDeviceInternal = false); + const BufferData& BuffData, + bool bIsDeviceInternal); + BufferGLImpl(IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator &BuffViewObjMemAllocator, + class RenderDeviceGLImpl *pDeviceGL, + const BufferDesc& BuffDesc, + GLuint GLHandle, + bool bIsDeviceInternal); ~BufferGLImpl(); /// Queries the specific interface, see IObject::QueryInterface() for details @@ -56,11 +62,14 @@ public: 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, MAP_TYPE MapType )override; + virtual void Unmap( IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapFlags )override; void BufferMemoryBarrier( Uint32 RequiredBarriers, class GLContextState &GLContextState ); - const GLObjectWrappers::GLBufferObj& GetGLBufferHandle(){ return m_GlBuffer; } + const GLObjectWrappers::GLBufferObj& GetGLHandle(){ return m_GlBuffer; } + + virtual GLuint GetGLBufferHandle()override final { return GetGLHandle(); } + virtual void* GetNativeHandle()override final { return reinterpret_cast(static_cast(GetGLBufferHandle())); } private: virtual void CreateViewInternal( const struct BufferViewDesc &ViewDesc, class IBufferView **ppView, bool bIsDefaultView )override; @@ -70,8 +79,8 @@ private: GLObjectWrappers::GLBufferObj m_GlBuffer; Uint32 m_uiMapTarget; - GLenum m_GLUsageHint; - Bool m_bUseMapWriteDiscardBugWA; + const GLenum m_GLUsageHint; + const Bool m_bUseMapWriteDiscardBugWA; }; } diff --git a/Graphics/GraphicsEngineOpenGL/include/BufferViewGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/BufferViewGLImpl.h index 676c864d..30f2181f 100644 --- a/Graphics/GraphicsEngineOpenGL/include/BufferViewGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/BufferViewGLImpl.h @@ -33,17 +33,22 @@ namespace Diligent { class FixedBlockMemoryAllocator; +class IRenderDevice; +class IDeviceContext; +class BufferGLImpl; +struct BufferViewDesc; + /// Implementation of the Diligent::IBufferViewGL interface -class BufferViewGLImpl : public BufferViewBase +class BufferViewGLImpl : public BufferViewBase { public: - typedef BufferViewBase TBuffViewBase; + typedef BufferViewBase TBuffViewBase; - BufferViewGLImpl( FixedBlockMemoryAllocator& BuffViewObjAllocator, - class IRenderDevice *pDevice, - class IDeviceContext *pContext, - const struct BufferViewDesc& ViewDesc, - class BufferGLImpl *pBuffer, + BufferViewGLImpl( IReferenceCounters *pRefCounters, + IRenderDevice *pDevice, + IDeviceContext *pContext, + const BufferViewDesc& ViewDesc, + BufferGLImpl *pBuffer, bool bIsDefaultView); /// Queries the specific interface, see IObject::QueryInterface() for details diff --git a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h index 1c037fe0..25e1e21c 100644 --- a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h @@ -37,7 +37,7 @@ class DeviceContextGLImpl : public DeviceContextBase public: typedef DeviceContextBase TDeviceContextBase; - DeviceContextGLImpl( IMemoryAllocator &RawMemAllocator, class RenderDeviceGLImpl *pDeviceGL, bool bIsDeferred ); + DeviceContextGLImpl( IReferenceCounters *pRefCounters, class RenderDeviceGLImpl *pDeviceGL, bool bIsDeferred ); /// Queries the specific interface, see IObject::QueryInterface() for details. virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override final; @@ -53,7 +53,8 @@ public: virtual void SetBlendFactors(const float* pBlendFactors = nullptr)override final; virtual void SetVertexBuffers( Uint32 StartSlot, Uint32 NumBuffersSet, IBuffer **ppBuffers, Uint32 *pStrides, Uint32 *pOffsets, Uint32 Flags )override final; - virtual void ClearState()override final; + + virtual void InvalidateState()override final; virtual void SetIndexBuffer( IBuffer *pIndexBuffer, Uint32 ByteOffset )override final; @@ -77,11 +78,13 @@ public: virtual void ExecuteCommandList(class ICommandList *pCommandList)override final; + virtual bool UpdateCurrentGLContext()override final; + void BindProgramResources( Uint32 &NewMemoryBarriers, IShaderResourceBinding *pResBinding ); GLContextState &GetContextState(){return m_ContextState;} - void RebindRenderTargets(); + void CommitRenderTargets(); protected: friend class BufferGLImpl; diff --git a/Graphics/GraphicsEngineOpenGL/include/FBOCache.h b/Graphics/GraphicsEngineOpenGL/include/FBOCache.h index 109f2776..dbe66acf 100644 --- a/Graphics/GraphicsEngineOpenGL/include/FBOCache.h +++ b/Graphics/GraphicsEngineOpenGL/include/FBOCache.h @@ -38,6 +38,11 @@ public: FBOCache(); ~FBOCache(); + FBOCache(const FBOCache&) = delete; + FBOCache( FBOCache&&) = delete; + FBOCache& operator = (const FBOCache&) = delete; + FBOCache& operator = ( FBOCache&&) = delete; + const GLObjectWrappers::GLFrameBufferObj& GetFBO( Uint32 NumRenderTargets, ITextureView *ppRenderTargets[], ITextureView *pDepthStencil, diff --git a/Graphics/GraphicsEngineOpenGL/include/GLContext.h b/Graphics/GraphicsEngineOpenGL/include/GLContext.h new file mode 100644 index 00000000..2db25f4c --- /dev/null +++ b/Graphics/GraphicsEngineOpenGL/include/GLContext.h @@ -0,0 +1,32 @@ +/* Copyright 2015-2017 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 PLATFORM_WIN32 +#include "GLContextWindows.h" +#endif + +#ifdef ANDROID +#include "GLContextAndroid.h" +#endif diff --git a/Graphics/GraphicsEngineOpenGL/include/GLContextAndroid.h b/Graphics/GraphicsEngineOpenGL/include/GLContextAndroid.h index 5216fdbf..74d8d27f 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLContextAndroid.h +++ b/Graphics/GraphicsEngineOpenGL/include/GLContextAndroid.h @@ -31,12 +31,14 @@ namespace Diligent struct ContextInitInfo { SwapChainDesc SwapChainAttribs; - void *pNativeWndHandle; + void *pNativeWndHandle = nullptr; }; class GLContext { public: + typedef EGLContext NativeGLContextType; + GLContext( const ContextInitInfo &Info, DeviceCaps &DeviceCaps ); ~GLContext(); @@ -50,27 +52,27 @@ namespace Diligent EGLint Resume( ANativeWindow* window ); const SwapChainDesc& GetSwapChainDesc(){ return SwapChainAttribs_; } + + NativeGLContextType GetCurrentNativeGLContext(); private: //EGL configurations - ANativeWindow* window_; - EGLDisplay display_; - EGLSurface surface_; - EGLContext context_; + ANativeWindow* window_ = nullptr; + EGLDisplay display_ = EGL_NO_DISPLAY; + EGLSurface surface_ = EGL_NO_SURFACE; + EGLContext context_ = EGL_NO_CONTEXT; EGLConfig config_; //Screen parameters - int32_t color_size_; - int32_t depth_size_; - int32_t major_version_; - int32_t minor_version_; + int32_t color_size_ = 0; + int32_t depth_size_ = 0; + int32_t major_version_ = 0; + int32_t minor_version_ = 0; //Flags - bool gles_initialized_; - bool egl_context_initialized_; - bool es3_supported_; - float gl_version_; - bool context_valid_; + bool gles_initialized_ = false; + bool egl_context_initialized_ = false; + bool context_valid_ = false; SwapChainDesc SwapChainAttribs_; @@ -78,6 +80,7 @@ namespace Diligent void Terminate(); bool InitEGLSurface(); bool InitEGLContext(); + void AttachToCurrentEGLContext(); void FillDeviceCaps( DeviceCaps &DeviceCaps ); }; } diff --git a/Graphics/GraphicsEngineOpenGL/include/GLContextState.h b/Graphics/GraphicsEngineOpenGL/include/GLContextState.h index 93ac12f6..61d9df1b 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLContextState.h +++ b/Graphics/GraphicsEngineOpenGL/include/GLContextState.h @@ -26,6 +26,7 @@ #include "GraphicsTypes.h" #include "GLObjectWrapper.h" #include "UniqueIdentifier.h" +#include "GLContext.h" namespace Diligent { @@ -65,11 +66,17 @@ public: void SetBlendFactors(const float *BlendFactors); void SetBlendState(const BlendStateDesc &BSDsc, Uint32 SampleMask); - Bool GetDepthWritesEnabled(){ return m_DepthWritesEnableState; } + Bool GetDepthWritesEnabled(){ return m_DSState.m_DepthWritesEnableState; } Bool GetScissorTestEnabled(){ return m_RSState.ScissorTestEnable; } void GetColorWriteMask( Uint32 RTIndex, Uint32 &WriteMask, Bool &bIsIndependent ); void SetColorWriteMask( Uint32 RTIndex, Uint32 WriteMask, Bool bIsIndependent ); + void SetNumPatchVertices( Int32 NumVertices); + void Invalidate(); + + void SetCurrentGLContext(GLContext::NativeGLContextType Context) { m_CurrentGLContext = Context; } + GLContext::NativeGLContextType GetCurrentGLContext()const { return m_CurrentGLContext; } + 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 @@ -78,27 +85,29 @@ private: // 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; + Diligent::UniqueIdentifier m_GLProgId = -1; + Diligent::UniqueIdentifier m_GLPipelineId = -1; + Diligent::UniqueIdentifier m_VAOId = -1; + Diligent::UniqueIdentifier m_FBOId = -1; 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; + Diligent::UniqueIdentifier InterfaceID = -1; + GLint MipLevel = 0; + GLboolean IsLayered = 0; + GLint Layer = 0; + GLenum Access = 0; + GLenum Format = 0; - BoundImageInfo( Diligent::UniqueIdentifier _UniqueID = 0, - GLint _MipLevel = 0, - GLboolean _IsLayered = 0, - GLint _Layer = 0, - GLenum _Access = 0, - GLenum _Format = 0) : + BoundImageInfo() {}; + + BoundImageInfo( Diligent::UniqueIdentifier _UniqueID, + GLint _MipLevel, + GLboolean _IsLayered, + GLint _Layer, + GLenum _Access, + GLenum _Format) : InterfaceID (_UniqueID ), MipLevel (_MipLevel ), IsLayered (_IsLayered), @@ -109,7 +118,7 @@ private: bool operator==(const BoundImageInfo &rhs)const { - return InterfaceID == rhs.InterfaceID && + return InterfaceID == rhs.InterfaceID && MipLevel == rhs.MipLevel && IsLayered == rhs.IsLayered && Layer == rhs.Layer && @@ -117,24 +126,24 @@ private: Format == rhs.Format; } }; - std::vector< BoundImageInfo > m_pBoundImages; - Uint32 m_PendingMemoryBarriers; + std::vector< BoundImageInfo > m_BoundImages; + + Uint32 m_PendingMemoryBarriers = 0; class EnableStateHelper { public: - enum class ENABLE_STATE + enum class ENABLE_STATE : Int32 { 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; + return (bEnabled && m_EnableState == ENABLE_STATE::ENABLED) || + (!bEnabled && m_EnableState == ENABLE_STATE::DISABLED); } bool operator != (bool bEnabled) const { @@ -153,62 +162,51 @@ private: } private: - ENABLE_STATE m_EnableState; + ENABLE_STATE m_EnableState = ENABLE_STATE::UNKNOWN; }; - EnableStateHelper m_DepthEnableState; - EnableStateHelper m_DepthWritesEnableState; - COMPARISON_FUNCTION m_DepthCmpFunc; - EnableStateHelper m_StencilTestEnableState; - Uint8 m_StencilReadMask; - Uint8 m_StencilWriteMask; - struct StencilOpState + + struct DepthStencilGLState { - COMPARISON_FUNCTION Func; - STENCIL_OP StencilFailOp; - STENCIL_OP StencilDepthFailOp; - STENCIL_OP StencilPassOp; - Int32 Ref; - Uint32 Mask; - StencilOpState() : - Func( COMPARISON_FUNC_UNKNOWN ), - StencilFailOp(STENCIL_OP_UNDEFINED), - StencilDepthFailOp( STENCIL_OP_UNDEFINED ), - StencilPassOp( STENCIL_OP_UNDEFINED ), - Ref( -1 ), - Mask( -1 ) - {} - }m_StencilOpState[2]; + EnableStateHelper m_DepthEnableState; + EnableStateHelper m_DepthWritesEnableState; + COMPARISON_FUNCTION m_DepthCmpFunc = COMPARISON_FUNC_UNKNOWN; + EnableStateHelper m_StencilTestEnableState; + Uint16 m_StencilReadMask = 0xFFFF; + Uint16 m_StencilWriteMask = 0xFFFF; + struct StencilOpState + { + COMPARISON_FUNCTION Func = COMPARISON_FUNC_UNKNOWN; + STENCIL_OP StencilFailOp = STENCIL_OP_UNDEFINED; + STENCIL_OP StencilDepthFailOp = STENCIL_OP_UNDEFINED; + STENCIL_OP StencilPassOp = STENCIL_OP_UNDEFINED; + Int32 Ref = std::numeric_limits::min(); + Uint32 Mask = static_cast(-1); + }m_StencilOpState[2]; + }m_DSState; struct RasterizerGLState { - FILL_MODE FillMode; - CULL_MODE CullMode; + FILL_MODE FillMode = FILL_MODE_UNDEFINED; + CULL_MODE CullMode = CULL_MODE_UNDEFINED; EnableStateHelper FrontCounterClockwise; - float fDepthBias; - float fSlopeScaledDepthBias; + float fDepthBias = std::numeric_limits::max(); + float fSlopeScaledDepthBias = std::numeric_limits::max(); EnableStateHelper DepthClampEnable; EnableStateHelper ScissorTestEnable; - RasterizerGLState() : - FillMode(FILL_MODE_UNDEFINED), - CullMode(CULL_MODE_UNDEFINED), - fDepthBias( std::numeric_limits::max() ), - fSlopeScaledDepthBias( std::numeric_limits::max() ) - {} }m_RSState; struct ContextCaps { - bool bFillModeSelectionSupported; - GLint m_iMaxCombinedTexUnits; - ContextCaps() : - bFillModeSelectionSupported(True), - m_iMaxCombinedTexUnits(0) - {} + bool bFillModeSelectionSupported = True; + GLint m_iMaxCombinedTexUnits = 0; }m_Caps; - Uint32 m_ColorWriteMasks[MaxRenderTargets]; + Uint32 m_ColorWriteMasks[MaxRenderTargets] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; EnableStateHelper m_bIndependentWriteMasks; - Int32 m_iActiveTexture; + Int32 m_iActiveTexture = -1; + Int32 m_NumPatchVertices = -1; + + GLContext::NativeGLContextType m_CurrentGLContext = {}; }; } diff --git a/Graphics/GraphicsEngineOpenGL/include/GLContextWindows.h b/Graphics/GraphicsEngineOpenGL/include/GLContextWindows.h index 5c3d92bc..adc2984a 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLContextWindows.h +++ b/Graphics/GraphicsEngineOpenGL/include/GLContextWindows.h @@ -29,18 +29,22 @@ namespace Diligent struct ContextInitInfo { SwapChainDesc SwapChainAttribs; - void *pNativeWndHandle; + void *pNativeWndHandle = nullptr; }; class GLContext { public: + typedef HGLRC NativeGLContextType; + GLContext( const ContextInitInfo &Info, struct DeviceCaps &DeviceCaps ); ~GLContext(); void SwapBuffers(); const SwapChainDesc& GetSwapChainDesc(){ return m_SwapChainAttribs; } + NativeGLContextType GetCurrentNativeGLContext(); + private: HGLRC m_Context; HDC m_WindowHandleToDeviceContext; diff --git a/Graphics/GraphicsEngineOpenGL/include/GLObjectWrapper.h b/Graphics/GraphicsEngineOpenGL/include/GLObjectWrapper.h index ef22f830..8736db4f 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLObjectWrapper.h +++ b/Graphics/GraphicsEngineOpenGL/include/GLObjectWrapper.h @@ -41,10 +41,7 @@ public: Create(); if(!m_uiHandle) { - std::string ErrorStr("Failed to create "); - ErrorStr += m_CreateReleaseHelper.Name; - ErrorStr += " object"; - LOG_ERROR_AND_THROW(ErrorStr.c_str()); + LOG_ERROR_AND_THROW("Failed to create ", m_CreateReleaseHelper.Name, " GL object"); } } } @@ -114,9 +111,29 @@ private: class GLBufferObjCreateReleaseHelper { public: - static void Create(GLuint &BuffObj){ glGenBuffers (1, &BuffObj); } - static void Release(GLuint BuffObj){ glDeleteBuffers(1, &BuffObj); } + explicit GLBufferObjCreateReleaseHelper(GLuint ExternalGLBufferHandle = 0) : + m_ExternalGLBufferHandle(ExternalGLBufferHandle) + {} + + void Create(GLuint &BuffObj) + { + if (m_ExternalGLBufferHandle != 0) + BuffObj = m_ExternalGLBufferHandle; // Attach to external GL buffer handle + else + glGenBuffers(1, &BuffObj); + } + + void Release(GLuint BuffObj) + { + if (m_ExternalGLBufferHandle != 0) + m_ExternalGLBufferHandle = 0; // Detach from external GL buffer. DO NOT delete the buffer + else + glDeleteBuffers(1, &BuffObj); + } static const char *Name; + +private: + GLuint m_ExternalGLBufferHandle; }; typedef GLObjWrapper GLBufferObj; @@ -167,9 +184,30 @@ typedef GLObjWrapper GLVertexArrayObj; class GLTextureCreateReleaseHelper { public: - void Create(GLuint &Tex) { glGenTextures(1, &Tex); } - void Release(GLuint Tex) { glDeleteTextures(1, &Tex); } + explicit GLTextureCreateReleaseHelper(GLuint ExternalGLTextureHandle = 0) : + m_ExternalGLTextureHandle(ExternalGLTextureHandle) + {} + + void Create(GLuint &Tex) + { + if (m_ExternalGLTextureHandle != 0) + Tex = m_ExternalGLTextureHandle; // Attach to the external texture + else + glGenTextures(1, &Tex); + } + + void Release(GLuint Tex) + { + if (m_ExternalGLTextureHandle != 0) + m_ExternalGLTextureHandle = 0; // Detach from the external texture. DO NOT delete it! + else + glDeleteTextures(1, &Tex); + } + static const char *Name; + +private: + GLuint m_ExternalGLTextureHandle; }; typedef GLObjWrapper GLTextureObj; diff --git a/Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions.h b/Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions.h deleted file mode 100644 index 3c058506..00000000 --- a/Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions.h +++ /dev/null @@ -1,957 +0,0 @@ -/* Copyright 2015-2017 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 deleted file mode 100644 index 337e464a..00000000 --- a/Graphics/GraphicsEngineOpenGL/include/GLSLDefinitions_inc.h +++ /dev/null @@ -1,957 +0,0 @@ -"/* Copyright 2015-2017 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 index fbe2791a..fa9eff34 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLStubs.h +++ b/Graphics/GraphicsEngineOpenGL/include/GLStubs.h @@ -474,23 +474,19 @@ # 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 GL_ES_VERSION_3_1 +#define LOAD_GL_BIND_IMAGE_TEXTURE +typedef void (GL_APIENTRY* PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +extern PFNGLBINDIMAGETEXTUREPROC glBindImageTexture; -#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 +#define LOAD_GL_DISPATCH_COMPUTE +typedef void (GL_APIENTRY* PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +extern PFNGLDISPATCHCOMPUTEPROC glDispatchCompute; -#ifndef glMemoryBarrier - #define LOAD_GL_MEMORY_BARRIER - typedef void (* PFNGLMEMORYBARRIERPROC) (GLbitfield barriers); - extern PFNGLMEMORYBARRIERPROC glMemoryBarrier; -#endif +#define LOAD_GL_MEMORY_BARRIER +typedef void (GL_APIENTRY* PFNGLMEMORYBARRIERPROC) (GLbitfield barriers); +extern PFNGLMEMORYBARRIERPROC glMemoryBarrier; +#endif // GL_ES_VERSION_3_1 #ifndef GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT # define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001 @@ -542,6 +538,23 @@ #endif +//--------------------------- Texture queries ----------------------------- +#ifndef GL_TEXTURE_WIDTH +# define GL_TEXTURE_WIDTH 0x1000 +#endif + +#ifndef GL_TEXTURE_HEIGHT +# define GL_TEXTURE_HEIGHT 0x1001 +#endif + +#ifndef GL_TEXTURE_DEPTH +# define GL_TEXTURE_DEPTH 0x8071 +#endif + +#ifndef GL_TEXTURE_INTERNAL_FORMAT +# define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#endif + //------------------------ Program interface query ------------------------ #ifndef GL_UNIFORM @@ -860,6 +873,15 @@ # define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC #endif +/* ---------------------- ARB_tessellation_shader --------------------- */ +#ifndef GL_PATCHES +# define GL_PATCHES 0xE +#endif + +#ifndef GL_PATCH_VERTICES +# define GL_PATCH_VERTICES 0x8E72 +#endif + // Define unsupported GL function stubs template @@ -868,192 +890,126 @@ void UnsupportedGLFunctionStub( const T &Name ) LOG_ERROR_MESSAGE( Name, "() is not supported in this API!\n" ); } -#ifndef glGenProgramPipelines +#define glDrawElementsInstancedBaseVertexBaseInstance(...) UnsupportedGLFunctionStub("glDrawElementsInstancedBaseVertexBaseInstance") +#define glDrawElementsInstancedBaseVertex(...) UnsupportedGLFunctionStub("glDrawElementsInstancedBaseVertex") +#define glDrawElementsInstancedBaseInstance(...) UnsupportedGLFunctionStub("glDrawElementsInstancedBaseInstance") +#define glDrawArraysInstancedBaseInstance(...) UnsupportedGLFunctionStub("glDrawArraysInstancedBaseInstance") +#define glDrawElementsBaseVertex(...) UnsupportedGLFunctionStub("glDrawElementsBaseVertex") +#define glTextureView(...) UnsupportedGLFunctionStub("glTextureView") +#define glTexStorage1D(...) UnsupportedGLFunctionStub("glTexStorage1D") +#define glTexSubImage1D(...) UnsupportedGLFunctionStub("glTexSubImage1D") +#define glTexStorage3DMultisample(...) UnsupportedGLFunctionStub("glTexStorage3DMultisample") + +#ifndef GL_ES_VERSION_3_1 + #define LOAD_GEN_PROGRAM_PIPELINES - typedef void (* PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint* pipelines); + typedef void (GL_APIENTRY* 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); + typedef void (GL_APIENTRY* PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint* pipelines); extern PFNGLDELETEPROGRAMPIPELINESPROC glDeleteProgramPipelines; -#endif -#ifndef glBindProgramPipeline #define LOAD_GL_BIND_PROGRAM_PIPELINE - typedef void (* PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); + typedef void (GL_APIENTRY* PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); extern PFNGLBINDPROGRAMPIPELINEPROC glBindProgramPipeline; -#endif -#ifndef glDrawElementsIndirect #define LOAD_DRAW_ELEMENTS_INDIRECT - typedef void (* PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const GLvoid *indirect); + typedef void (GL_APIENTRY* 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 ); + typedef void (GL_APIENTRY* PFNGLDRAWARRAYSINDIRECTPROC)( GLenum mode, const GLvoid *indirect ); extern PFNGLDRAWARRAYSINDIRECTPROC glDrawArraysIndirect; -#endif -#ifndef glDispatchComputeIndirect #define LOAD_DISPATCH_COMPUTE_INDIRECT - typedef void (* PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect); + typedef void (GL_APIENTRY* 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); + typedef void (GL_APIENTRY* 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); + typedef void (GL_APIENTRY* 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); + typedef void (GL_APIENTRY* 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); + typedef void (GL_APIENTRY* 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); + typedef void (GL_APIENTRY* 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); + typedef void (GL_APIENTRY* 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 + #define LOAD_GET_TEX_LEVEL_PARAMETER_IV + typedef void (GL_APIENTRY* PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params); + extern PFNGLGETTEXLEVELPARAMETERIVPROC glGetTexLevelParameteriv; +#endif //GL_ES_VERSION_3_1 -#ifndef glEnablei - #define LOAD_GL_ENABLEI - typedef void (* PFNGLENABLEIPROC) (GLenum, GLuint); - extern PFNGLENABLEIPROC glEnablei; -#endif +#define LOAD_GL_TEX_BUFFER +typedef void (GL_APIENTRY* PFNGLTEXBUFFERPROC) (GLenum, GLenum, GLuint); +extern PFNGLTEXBUFFERPROC glTexBuffer; -#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 +#define LOAD_GL_VIEWPORT_INDEXEDF +typedef void (GL_APIENTRY* PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +extern PFNGLVIEWPORTINDEXEDFPROC glViewportIndexedf; -#ifndef glBlendEquationSeparatei - #define LOAD_GL_BLEND_EQUATION_SEPARATEI - typedef void (* PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); - extern PFNGLBLENDEQUATIONSEPARATEIPROC glBlendEquationSeparatei; -#endif +#define LOAD_GL_SCISSOR_INDEXED +typedef void (GL_APIENTRY* PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); +extern PFNGLSCISSORINDEXEDPROC glScissorIndexed; -#ifndef glDisablei - #define LOAD_GL_DISABLEI - typedef void (* PFNGLDISABLEIPROC) (GLenum, GLuint); - extern PFNGLDISABLEIPROC glDisablei; -#endif +#define LOAD_GL_POLYGON_MODE +typedef void (GL_APIENTRY* PFNGLPOLYGONMODE) (GLenum face, GLenum mode); +extern PFNGLPOLYGONMODE glPolygonMode; -#ifndef glColorMaski - #define LOAD_GL_COLOR_MASKI - typedef void (* PFNGLCOLORMASKIPROC) (GLuint, GLboolean, GLboolean, GLboolean, GLboolean); - extern PFNGLCOLORMASKIPROC glColorMaski; -#endif +#define LOAD_GL_ENABLEI +typedef void (GL_APIENTRY* PFNGLENABLEIPROC) (GLenum, GLuint); +extern PFNGLENABLEIPROC glEnablei; -#ifndef glViewportIndexedf - #define LOAD_GL_VIEWPORT_INDEXEDF - typedef void (* PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); - extern PFNGLVIEWPORTINDEXEDFPROC glViewportIndexedf; -#endif +#define LOAD_GL_BLEND_FUNC_SEPARATEI +typedef void (GL_APIENTRY* PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +extern PFNGLBLENDFUNCSEPARATEIPROC glBlendFuncSeparatei; -#ifndef glScissorIndexed - #define LOAD_GL_SCISSOR_INDEXED - typedef void (* PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); - extern PFNGLSCISSORINDEXEDPROC glScissorIndexed; -#endif +#define LOAD_GL_BLEND_EQUATION_SEPARATEI +typedef void (GL_APIENTRY* PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +extern PFNGLBLENDEQUATIONSEPARATEIPROC glBlendEquationSeparatei; -#ifndef glFramebufferTexture - #define LOAD_GL_FRAMEBUFFER_TEXTURE - typedef void (* PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum, GLenum, GLuint, GLint); - extern PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture; -#endif +#define LOAD_GL_DISABLEI +typedef void (GL_APIENTRY* PFNGLDISABLEIPROC) (GLenum, GLuint); +extern PFNGLDISABLEIPROC glDisablei; -#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 +#define LOAD_GL_COLOR_MASKI +typedef void (GL_APIENTRY* PFNGLCOLORMASKIPROC) (GLuint, GLboolean, GLboolean, GLboolean, GLboolean); +extern PFNGLCOLORMASKIPROC glColorMaski; -#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 +#define LOAD_GL_PATCH_PARAMTER_I +typedef void (GL_APIENTRY* PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value); +extern PFNGLPATCHPARAMETERIPROC glPatchParameteri; -#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 +#define LOAD_GL_FRAMEBUFFER_TEXTURE +typedef void (GL_APIENTRY* PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum, GLenum, GLuint, GLint); +extern PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture; + +#define LOAD_GL_FRAMEBUFFER_TEXTURE_1D +typedef void (GL_APIENTRY* PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D; + +#define LOAD_GL_FRAMEBUFFER_TEXTURE_3D +typedef void (GL_APIENTRY* PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer); +extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D; + +#define LOAD_GL_COPY_IMAGE_SUB_DATA +typedef void (GL_APIENTRY* 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; void LoadGLFunctions(); \ No newline at end of file diff --git a/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.h b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.h index 60efec17..0e55ddef 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.h +++ b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.h @@ -156,6 +156,7 @@ inline void FilterTypeToGLFilterType(FILTER_TYPE Filter, GLenum &GLFilter, Bool } GLenum TexFormatToGLInternalTexFormat(TEXTURE_FORMAT TexFormat, Uint32 BindFlags = 0); +TEXTURE_FORMAT GLInternalTexFormatToTexFormat(GLenum GlFormat); GLenum CorrectGLTexFormat(GLenum GLTexFormat, Uint32 BindFlags); inline GLenum TexAddressModeToGLAddressMode(TEXTURE_ADDRESS_MODE Mode) diff --git a/Graphics/GraphicsEngineOpenGL/include/HLSL2GLSLConverter.h b/Graphics/GraphicsEngineOpenGL/include/HLSL2GLSLConverter.h deleted file mode 100644 index ce74d7ef..00000000 --- a/Graphics/GraphicsEngineOpenGL/include/HLSL2GLSLConverter.h +++ /dev/null @@ -1,424 +0,0 @@ -/* Copyright 2015-2017 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 -#include - -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 -> 4 - // Texture2D -> 1 - // Texture2D -> 0 - HLSLObjectInfo( const String& Type, Uint32 NComp ) : - GLSLType( Type ), - NumComponents( NComp ) - {} - }; - typedef std::unordered_map 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 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 TokenListType; - typedef std::unordered_map 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 &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 - 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& Params ); - void ProcessFragmentShaderArguments( std::vector& Params, - String &GlobalVariables, - String &Epilogue, - String &Prologue ); - void ProcessVertexShaderArguments( std::vector& Params, - String &GlobalVariables, - String &Epilogue, - String &Prologue ); - void ProcessComputeShaderArguments( TokenListType::iterator &TypeToken, - std::vector& 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 m_HLSLKeywords; - - // Set of all GLSL image types (image1D, uimage1D, iimage1D, image2D, ... ) - std::unordered_set m_ImageTypes; - - // Set of all HLSL atomic operations (InterlockedAdd, InterlockedOr, ...) - std::unordered_set 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 -> sampler2D -// - Texture3D -> usampler3D -// - Texture2DArray -> isampler2DArray -// - Texture2D -> sampler2D -// - To distinguish if sampler should be shadow or not, the converter tries to find _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 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 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/PipelineStateGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.h index 99e077f4..5f3e6e67 100644 --- a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.h @@ -28,6 +28,7 @@ #include "RenderDevice.h" #include "GLProgram.h" #include "GLObjectWrapper.h" +#include "GLContext.h" namespace Diligent { @@ -35,12 +36,12 @@ namespace Diligent class FixedBlockMemoryAllocator; /// Implementation of the Diligent::IPipelineStateGL interface -class PipelineStateGLImpl : public PipelineStateBase +class PipelineStateGLImpl : public PipelineStateBase { public: - typedef PipelineStateBase TPipelineStateBase; + typedef PipelineStateBase TPipelineStateBase; - PipelineStateGLImpl(FixedBlockMemoryAllocator &PSOAllocator, class RenderDeviceGLImpl *pDeviceGL, const PipelineStateDesc& PipelineDesc, bool IsDeviceInternal = false); + PipelineStateGLImpl(IReferenceCounters *pRefCounters, class RenderDeviceGLImpl *pDeviceGL, const PipelineStateDesc& PipelineDesc, bool IsDeviceInternal = false); ~PipelineStateGLImpl(); /// Queries the specific interface, see IObject::QueryInterface() for details @@ -51,12 +52,14 @@ public: virtual void CreateShaderResourceBinding( IShaderResourceBinding **ppShaderResourceBinding )override; GLProgram &GetGLProgram(){return m_GLProgram;} - GLObjectWrappers::GLPipelineObj &GetGLProgramPipeline(){return m_GLProgPipeline;} + GLObjectWrappers::GLPipelineObj &GetGLProgramPipeline(GLContext::NativeGLContextType Context); + private: void LinkGLProgram(bool bIsProgramPipelineSupported); GLProgram m_GLProgram; - GLObjectWrappers::GLPipelineObj m_GLProgPipeline; + ThreadingTools::LockFlag m_ProgPipelineLockFlag; + std::unordered_map m_GLProgPipelines; }; } diff --git a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLESImpl.h b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLESImpl.h index 69b526f1..e31786b9 100644 --- a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLESImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLESImpl.h @@ -31,7 +31,7 @@ namespace Diligent class RenderDeviceGLESImpl : public RenderDeviceGLImpl { public: - RenderDeviceGLESImpl( IMemoryAllocator &RawMemAllocator, const ContextInitInfo &InitInfo ); + RenderDeviceGLESImpl( IReferenceCounters *pRefCounters, IMemoryAllocator &RawMemAllocator, const ContextInitInfo &InitInfo ); virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface ); diff --git a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h index 7ee04f4e..e9938011 100644 --- a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h @@ -24,15 +24,7 @@ #pragma once #include "RenderDeviceBase.h" - -#ifdef PLATFORM_WIN32 -#include "GLContextWindows.h" -#endif - -#ifdef ANDROID -#include "GLContextAndroid.h" -#endif - +#include "GLContext.h" #include "VAOCache.h" #include "BaseInterfacesGL.h" #include "FBOCache.h" @@ -63,27 +55,38 @@ class RenderDeviceGLImpl : public RenderDeviceBase public: typedef RenderDeviceBase TRenderDeviceBase; - RenderDeviceGLImpl( IMemoryAllocator &RawMemAllocator, const ContextInitInfo &InitInfo ); + RenderDeviceGLImpl( IReferenceCounters *pRefCounters, IMemoryAllocator &RawMemAllocator, 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; + virtual void CreateBuffer(const BufferDesc& BuffDesc, const BufferData &BuffData, IBuffer **ppBufferLayout)override final; void CreateShader(const ShaderCreationAttribs &ShaderCreationAttribs, IShader **ppShader, bool bIsDeviceInternal ); - virtual void CreateShader(const ShaderCreationAttribs &ShaderCreationAttribs, IShader **ppShader)override; + virtual void CreateShader(const ShaderCreationAttribs &ShaderCreationAttribs, IShader **ppShader)override final; void CreateTexture(const TextureDesc& TexDesc, const TextureData &Data, ITexture **ppTexture, bool bIsDeviceInternal); - virtual void CreateTexture(const TextureDesc& TexDesc, const TextureData &Data, ITexture **ppTexture)override; + virtual void CreateTexture(const TextureDesc& TexDesc, const TextureData &Data, ITexture **ppTexture)override final; void CreateSampler(const SamplerDesc& SamplerDesc, ISampler **ppSampler, bool bIsDeviceInternal); - virtual void CreateSampler(const SamplerDesc& SamplerDesc, ISampler **ppSampler)override; + virtual void CreateSampler(const SamplerDesc& SamplerDesc, ISampler **ppSampler)override final; void CreatePipelineState( const PipelineStateDesc &PipelineDesc, IPipelineState **ppPipelineState, bool bIsDeviceInternal); - virtual void CreatePipelineState( const PipelineStateDesc &PipelineDesc, IPipelineState **ppPipelineState )override; + virtual void CreatePipelineState( const PipelineStateDesc &PipelineDesc, IPipelineState **ppPipelineState )override final; + virtual void CreateTextureFromGLHandle(Uint32 GLHandle, const TextureDesc &TexDesc, ITexture **ppTexture)override final; + + virtual void CreateBufferFromGLHandle(Uint32 GLHandle, const BufferDesc &BuffDesc, IBuffer **ppBuffer)override final; + const GPUInfo& GetGPUInfo(){ return m_GPUInfo; } + FBOCache& GetFBOCache(GLContext::NativeGLContextType Context); + void OnReleaseTexture(ITexture *pTexture); + + VAOCache& GetVAOCache(GLContext::NativeGLContextType Context); + void OnDestroyPSO(IPipelineState *pPSO); + void OnDestroyBuffer(IBuffer *pBuffer); + protected: friend class DeviceContextGLImpl; friend class TextureBaseGL; @@ -92,26 +95,25 @@ protected: friend class BufferGLImpl; friend class TextureViewGLImpl; friend class SwapChainGLImpl; + friend class GLContextState; // Must be the first member because its constructor initializes OpenGL GLContext m_GLContext; std::unordered_set m_ExtensionStrings; - VAOCache m_VAOCache; - FBOCache m_FBOCache; + ThreadingTools::LockFlag m_VAOCacheLockFlag; + std::unordered_map m_VAOCache; - GPUInfo m_GPUInfo; + ThreadingTools::LockFlag m_FBOCacheLockFlag; + std::unordered_map m_FBOCache; - // 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; + GPUInfo m_GPUInfo; TexRegionRender m_TexRegionRender; - + private: - virtual void TestTextureFormat( TEXTURE_FORMAT TexFormat ); + virtual void TestTextureFormat( TEXTURE_FORMAT TexFormat )override; bool CheckExtension(const Char *ExtensionString); void FlagSupportedTexFormats(); void QueryDeviceCaps(); diff --git a/Graphics/GraphicsEngineOpenGL/include/SamplerGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/SamplerGLImpl.h index 178564f5..dfe3c984 100644 --- a/Graphics/GraphicsEngineOpenGL/include/SamplerGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/SamplerGLImpl.h @@ -34,12 +34,12 @@ namespace Diligent class FixedBlockMemoryAllocator; /// Implementation of the Diligent::ISamplerGL interface -class SamplerGLImpl : public SamplerBase +class SamplerGLImpl : public SamplerBase { public: - typedef SamplerBase TSamplerBase; + typedef SamplerBase TSamplerBase; - SamplerGLImpl( FixedBlockMemoryAllocator &SamplerObjAllocator, class RenderDeviceGLImpl *pDeviceGL, const SamplerDesc& SamplerDesc, bool bIsDeviceInternal = false ); + SamplerGLImpl( IReferenceCounters *pRefCounters, class RenderDeviceGLImpl *pDeviceGL, const SamplerDesc& SamplerDesc, bool bIsDeviceInternal = false ); ~SamplerGLImpl(); virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface ); diff --git a/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h index 5892428f..88b12a3d 100644 --- a/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h @@ -64,12 +64,12 @@ inline GLenum ShaderTypeToGLShaderBit(SHADER_TYPE ShaderType) } /// Implementation of the Diligent::IShaderGL interface -class ShaderGLImpl : public ShaderBase +class ShaderGLImpl : public ShaderBase { public: - typedef ShaderBase TShaderBase; + typedef ShaderBase TShaderBase; - ShaderGLImpl( FixedBlockMemoryAllocator& ShaderObjAllocator, class RenderDeviceGLImpl *pDeviceGL, const ShaderCreationAttribs &ShaderCreationAttribs, bool bIsDeviceInternal = false ); + ShaderGLImpl( IReferenceCounters *pRefCounters, class RenderDeviceGLImpl *pDeviceGL, const ShaderCreationAttribs &ShaderCreationAttribs, bool bIsDeviceInternal = false ); ~ShaderGLImpl(); virtual void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags )override; diff --git a/Graphics/GraphicsEngineOpenGL/include/ShaderResourceBindingGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/ShaderResourceBindingGLImpl.h index 533a2d84..9645b3e2 100644 --- a/Graphics/GraphicsEngineOpenGL/include/ShaderResourceBindingGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/ShaderResourceBindingGLImpl.h @@ -37,11 +37,11 @@ namespace Diligent class FixedBlockMemoryAllocator; /// Implementation of the Diligent::IShaderResourceBindingGL interface -class ShaderResourceBindingGLImpl : public ShaderResourceBindingBase +class ShaderResourceBindingGLImpl : public ShaderResourceBindingBase { public: - typedef ShaderResourceBindingBase TBase; - ShaderResourceBindingGLImpl(FixedBlockMemoryAllocator& SRBAllocator, class PipelineStateGLImpl *pPSO); + typedef ShaderResourceBindingBase TBase; + ShaderResourceBindingGLImpl(IReferenceCounters *pRefCounters, class PipelineStateGLImpl *pPSO); ~ShaderResourceBindingGLImpl(); virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override; diff --git a/Graphics/GraphicsEngineOpenGL/include/SwapChainGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/SwapChainGLImpl.h index 7987d603..f6ac58ea 100644 --- a/Graphics/GraphicsEngineOpenGL/include/SwapChainGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/SwapChainGLImpl.h @@ -31,12 +31,12 @@ namespace Diligent class IMemoryAllocator; /// Implementation of the Diligent::ISwapChainGL interface -class SwapChainGLImpl : public SwapChainBase +class SwapChainGLImpl : public SwapChainBase { public: - typedef SwapChainBase TSwapChainBase; + typedef SwapChainBase TSwapChainBase; - SwapChainGLImpl(IMemoryAllocator &Allocator, + SwapChainGLImpl(IReferenceCounters *pRefCounters, const SwapChainDesc& SwapChainDesc, class RenderDeviceGLImpl* pRenderDeviceGL, class DeviceContextGLImpl* pImmediateContextGL); diff --git a/Graphics/GraphicsEngineOpenGL/include/TexRegionRender.h b/Graphics/GraphicsEngineOpenGL/include/TexRegionRender.h index f0006632..cb9aaa88 100644 --- a/Graphics/GraphicsEngineOpenGL/include/TexRegionRender.h +++ b/Graphics/GraphicsEngineOpenGL/include/TexRegionRender.h @@ -49,10 +49,10 @@ private: Diligent::RefCntAutoPtr m_pPSO[RESOURCE_DIM_NUM_DIMENSIONS * 3]; Diligent::RefCntAutoPtr m_pOrigPSO; - Uint32 m_OrigStencilRef; - float m_OrigBlendFactors[4]; - Uint32 m_NumRenderTargets; - ITextureView *m_pOrigRTVs[MaxRenderTargets]; + Uint32 m_OrigStencilRef = 0; + float m_OrigBlendFactors[4] = {}; + Uint32 m_NumRenderTargets = 0; + ITextureView *m_pOrigRTVs[MaxRenderTargets] = {}; Diligent::RefCntAutoPtr m_pOrigDSV; std::vector m_OrigViewports; }; diff --git a/Graphics/GraphicsEngineOpenGL/include/Texture1DArray_OGL.h b/Graphics/GraphicsEngineOpenGL/include/Texture1DArray_OGL.h index 8e9d52ab..fe5bd09e 100644 --- a/Graphics/GraphicsEngineOpenGL/include/Texture1DArray_OGL.h +++ b/Graphics/GraphicsEngineOpenGL/include/Texture1DArray_OGL.h @@ -31,17 +31,25 @@ namespace Diligent class Texture1DArray_OGL : public TextureBaseGL { public: - Texture1DArray_OGL( FixedBlockMemoryAllocator& TexObjAllocator, + Texture1DArray_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, class RenderDeviceGLImpl *pDeviceGL, class DeviceContextGLImpl *pDeviceContext, - const TextureDesc& BuffDesc, - const TextureData &InitData = TextureData(), + const TextureDesc& TexDesc, + const TextureData& InitData = TextureData(), bool bIsDeviceInternal = false); + + Texture1DArray_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceGLImpl *pDeviceGL, + class DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, + 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 ); + virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )override final; + virtual void AttachToFramebuffer( const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint )override final; private: diff --git a/Graphics/GraphicsEngineOpenGL/include/Texture1D_OGL.h b/Graphics/GraphicsEngineOpenGL/include/Texture1D_OGL.h index 451be77d..e16ecb6f 100644 --- a/Graphics/GraphicsEngineOpenGL/include/Texture1D_OGL.h +++ b/Graphics/GraphicsEngineOpenGL/include/Texture1D_OGL.h @@ -31,17 +31,25 @@ namespace Diligent class Texture1D_OGL : public TextureBaseGL { public: - Texture1D_OGL( FixedBlockMemoryAllocator& TexObjAllocator, + Texture1D_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, class RenderDeviceGLImpl *pDeviceGL, class DeviceContextGLImpl *pDeviceContext, - const TextureDesc& BuffDesc, - const TextureData &InitData = TextureData(), + const TextureDesc& TexDesc, + const TextureData& InitData = TextureData(), + bool bIsDeviceInternal = false); + + Texture1D_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceGLImpl *pDeviceGL, + class DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, 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 ); + virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )override final; + virtual void AttachToFramebuffer( const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint )override final; private: diff --git a/Graphics/GraphicsEngineOpenGL/include/Texture2DArray_OGL.h b/Graphics/GraphicsEngineOpenGL/include/Texture2DArray_OGL.h index ffd2b699..8792cd4c 100644 --- a/Graphics/GraphicsEngineOpenGL/include/Texture2DArray_OGL.h +++ b/Graphics/GraphicsEngineOpenGL/include/Texture2DArray_OGL.h @@ -31,17 +31,25 @@ namespace Diligent class Texture2DArray_OGL : public TextureBaseGL { public: - Texture2DArray_OGL( FixedBlockMemoryAllocator& TexObjAllocator, + Texture2DArray_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, class RenderDeviceGLImpl *pDeviceGL, class DeviceContextGLImpl *pDeviceContext, - const TextureDesc& BuffDesc, - const TextureData &InitData = TextureData(), + const TextureDesc& TexDesc, + const TextureData& InitData = TextureData(), bool bIsDeviceInternal = false ); + + Texture2DArray_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceGLImpl *pDeviceGL, + class DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, + 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 ); + virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )override final; + virtual void AttachToFramebuffer( const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint )override final; private: diff --git a/Graphics/GraphicsEngineOpenGL/include/Texture2D_OGL.h b/Graphics/GraphicsEngineOpenGL/include/Texture2D_OGL.h index f62d6400..9d7e9772 100644 --- a/Graphics/GraphicsEngineOpenGL/include/Texture2D_OGL.h +++ b/Graphics/GraphicsEngineOpenGL/include/Texture2D_OGL.h @@ -31,17 +31,25 @@ namespace Diligent class Texture2D_OGL : public TextureBaseGL { public: - Texture2D_OGL( FixedBlockMemoryAllocator& TexObjAllocator, + Texture2D_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, class RenderDeviceGLImpl *pDeviceGL, class DeviceContextGLImpl *pDeviceContext, - const TextureDesc& BuffDesc, - const TextureData &InitData = TextureData(), + const TextureDesc& TexDesc, + const TextureData& InitData = TextureData(), + bool bIsDeviceInternal = false); + + Texture2D_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceGLImpl *pDeviceGL, + class DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, 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 ); + virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )override final; + virtual void AttachToFramebuffer( const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint )override final; private: diff --git a/Graphics/GraphicsEngineOpenGL/include/Texture3D_OGL.h b/Graphics/GraphicsEngineOpenGL/include/Texture3D_OGL.h index 7409fa91..1e27b3a7 100644 --- a/Graphics/GraphicsEngineOpenGL/include/Texture3D_OGL.h +++ b/Graphics/GraphicsEngineOpenGL/include/Texture3D_OGL.h @@ -31,17 +31,25 @@ namespace Diligent class Texture3D_OGL : public TextureBaseGL { public: - Texture3D_OGL( FixedBlockMemoryAllocator& TexObjAllocator, + Texture3D_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, class RenderDeviceGLImpl *pDeviceGL, class DeviceContextGLImpl *pDeviceContext, - const TextureDesc& BuffDesc, - const TextureData &InitData = TextureData(), + const TextureDesc& TexDesc, + const TextureData& InitData = TextureData(), bool bIsDeviceInternal = false ); + + Texture3D_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceGLImpl *pDeviceGL, + class DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, + 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 ); + virtual void UpdateData(IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData)override final; + virtual void AttachToFramebuffer( const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint )override final; private: diff --git a/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h index 488650f1..767d6aac 100644 --- a/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h +++ b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h @@ -38,18 +38,28 @@ namespace Diligent class FixedBlockMemoryAllocator; /// Base implementation of the Diligent::ITextureGL interface -class TextureBaseGL : public TextureBase, public AsyncWritableResource +class TextureBaseGL : public TextureBase, public AsyncWritableResource { public: - typedef TextureBase TTextureBase; + typedef TextureBase TTextureBase; - TextureBaseGL(FixedBlockMemoryAllocator& TexObjAllocator, + TextureBaseGL(IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, class RenderDeviceGLImpl *pDeviceGL, const TextureDesc &TexDesc, GLenum BindTarget, const TextureData &InitData = TextureData(), bool bIsDeviceInternal = false); + + TextureBaseGL(IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceGLImpl *pDeviceGL, + class DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, + GLenum BindTarget, + bool bIsDeviceInternal); + ~TextureBaseGL(); virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override; @@ -57,11 +67,11 @@ public: virtual void UpdateData( class GLContextState &CtxState, IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData ); //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, MAP_TYPE MapType )override; + virtual void Map( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource &MappedData )override; + virtual void Unmap( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags )override; const GLObjectWrappers::GLTextureObj& GetGLHandle()const{ return m_GlTexture; } - GLenum GetBindTarget()const{return m_BindTarget;} + virtual GLenum GetBindTarget()const override final{return m_BindTarget;} GLenum GetGLTexFormat()const{ return m_GLTexFormat; } void TextureMemoryBarrier( Uint32 RequiredBarriers, class GLContextState &GLContextState); @@ -79,6 +89,9 @@ public: Uint32 DstY, Uint32 DstZ)override; + virtual GLuint GetGLTextureHandle()override final { return GetGLHandle(); } + virtual void* GetNativeHandle()override final { return reinterpret_cast(static_cast(GetGLTextureHandle())); } + protected: virtual void CreateViewInternal( const struct TextureViewDesc &ViewDesc, class ITextureView **ppView, bool bIsDefaultView )override; void SetDefaultGLParameters(); diff --git a/Graphics/GraphicsEngineOpenGL/include/TextureCubeArray_OGL.h b/Graphics/GraphicsEngineOpenGL/include/TextureCubeArray_OGL.h index 4067f5d7..b03c6eb8 100644 --- a/Graphics/GraphicsEngineOpenGL/include/TextureCubeArray_OGL.h +++ b/Graphics/GraphicsEngineOpenGL/include/TextureCubeArray_OGL.h @@ -31,17 +31,25 @@ namespace Diligent class TextureCubeArray_OGL : public TextureBaseGL { public: - TextureCubeArray_OGL( FixedBlockMemoryAllocator& TexObjAllocator, + TextureCubeArray_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, class RenderDeviceGLImpl *pDeviceGL, class DeviceContextGLImpl *pDeviceContext, - const TextureDesc& BuffDesc, - const TextureData &InitData = TextureData(), + const TextureDesc& TexDesc, + const TextureData& InitData = TextureData(), bool bIsDeviceInternal = false ); + + TextureCubeArray_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceGLImpl *pDeviceGL, + class DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, + bool bIsDeviceInternal = false); ~TextureCubeArray_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 ); + virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )override final; + virtual void AttachToFramebuffer( const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint )override final; private: diff --git a/Graphics/GraphicsEngineOpenGL/include/TextureCube_OGL.h b/Graphics/GraphicsEngineOpenGL/include/TextureCube_OGL.h index 42e9500a..df00331e 100644 --- a/Graphics/GraphicsEngineOpenGL/include/TextureCube_OGL.h +++ b/Graphics/GraphicsEngineOpenGL/include/TextureCube_OGL.h @@ -31,17 +31,25 @@ namespace Diligent class TextureCube_OGL : public TextureBaseGL { public: - TextureCube_OGL( FixedBlockMemoryAllocator& TexObjAllocator, + TextureCube_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, class RenderDeviceGLImpl *pDeviceGL, class DeviceContextGLImpl *pDeviceContext, - const TextureDesc& BuffDesc, - const TextureData &InitData = TextureData(), + const TextureDesc& TexDesc, + const TextureData& InitData = TextureData(), + bool bIsDeviceInternal = false); + + TextureCube_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceGLImpl *pDeviceGL, + class DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, bool bIsDeviceInternal = false); ~TextureCube_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 ); + virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )override final; + virtual void AttachToFramebuffer( const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint )override final; private: diff --git a/Graphics/GraphicsEngineOpenGL/include/TextureViewGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/TextureViewGLImpl.h index 2bfe34b8..83b12daa 100644 --- a/Graphics/GraphicsEngineOpenGL/include/TextureViewGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/TextureViewGLImpl.h @@ -34,12 +34,12 @@ namespace Diligent class FixedBlockMemoryAllocator; /// Implementation of the Diligent::ITextureViewGL interface -class TextureViewGLImpl : public TextureViewBase +class TextureViewGLImpl : public TextureViewBase { public: - typedef TextureViewBase TTextureViewBase; + typedef TextureViewBase TTextureViewBase; - TextureViewGLImpl( FixedBlockMemoryAllocator &TexViewObjAllocator, + TextureViewGLImpl(IReferenceCounters *pRefCounters, class IRenderDevice *pDevice, const struct TextureViewDesc& ViewDesc, class TextureBaseGL *pTexture, @@ -51,6 +51,7 @@ public: const GLObjectWrappers::GLTextureObj& GetHandle(); GLenum GetBindTarget(); + void SetBindTarget(GLenum ViewTexBindTarget) { m_ViewTexBindTarget = ViewTexBindTarget; } void GenerateMips( IDeviceContext *pContext )override; diff --git a/Graphics/GraphicsEngineOpenGL/include/VAOCache.h b/Graphics/GraphicsEngineOpenGL/include/VAOCache.h index 00e4d60c..ac469f16 100644 --- a/Graphics/GraphicsEngineOpenGL/include/VAOCache.h +++ b/Graphics/GraphicsEngineOpenGL/include/VAOCache.h @@ -40,11 +40,20 @@ public: VAOCache(); ~VAOCache(); + VAOCache(const VAOCache&) = delete; + VAOCache( VAOCache&&) = delete; + VAOCache& operator = (const VAOCache&) = delete; + VAOCache& operator = ( VAOCache&&) = delete; + + + const GLObjectWrappers::GLVertexArrayObj& GetVAO( IPipelineState *pPSO, - IBuffer *pIndexBuffer, - VertexStreamInfo VertexStreams[], - Uint32 NumVertexStreams, - class GLContextState &GLContextState); + IBuffer *pIndexBuffer, + VertexStreamInfo VertexStreams[], + Uint32 NumVertexStreams, + class GLContextState &GLContextState); + const GLObjectWrappers::GLVertexArrayObj& GetEmptyVAO(); + void OnDestroyBuffer(IBuffer *pBuffer); void OnDestroyPSO(IPipelineState *pPSO); @@ -52,22 +61,37 @@ private: // This structure is used as the key to find VAO struct VAOCacheKey { + VAOCacheKey(const IPipelineState* pso, const IBuffer* indBuffer) : + pPSO(pso), + pIndexBuffer(indBuffer), + NumUsedSlots(0) + {} + // Note that the the pointers are used for ordering only // They are not used to access the objects - IPipelineState* pPSO; - IBuffer* pIndexBuffer; + + // VAO encapsulates both input layout and all bound buffers + // PSO uniqly defines the layout (attrib pointers, divisors, etc.), + // so we do not need to add individual layout elements to the key + // The keey needs to contain all bound buffers + const IPipelineState* const pPSO; + const IBuffer* const pIndexBuffer; + Uint32 NumUsedSlots; struct StreamAttribs { - IBuffer* pBuffer; + const IBuffer* pBuffer; Uint32 Stride; Uint32 Offset; }Streams[MaxBufferSlots]; + mutable size_t Hash = 0; + bool operator == (const VAOCacheKey &Key)const { - return (pPSO == Key.pPSO) && - (pIndexBuffer == Key.pIndexBuffer) && - (memcmp(Streams, Key.Streams, sizeof(Streams)) == 0); + return pPSO == Key.pPSO && + pIndexBuffer == Key.pIndexBuffer && + NumUsedSlots == Key.NumUsedSlots && + memcmp(Streams, Key.Streams, sizeof(StreamAttribs) * NumUsedSlots) == 0; } }; @@ -75,21 +99,25 @@ private: { std::size_t operator() ( const VAOCacheKey& Key )const { - std::size_t Seed = 0; - HashCombine(Seed, Key.pPSO); - if(Key.pIndexBuffer) - HashCombine(Seed, Key.pIndexBuffer); - for(int iStream = 0; iStream < _countof(Key.Streams); ++iStream ) + if (Key.Hash == 0) { - auto &CurrStream = Key.Streams[iStream]; - if( CurrStream.pBuffer ) + std::size_t Seed = 0; + HashCombine(Seed, Key.pPSO, Key.NumUsedSlots); + if (Key.pIndexBuffer) + HashCombine(Seed, Key.pIndexBuffer); + for (Uint32 slot = 0; slot < Key.NumUsedSlots; ++slot) { - HashCombine(Seed, CurrStream.pBuffer); - HashCombine(Seed, CurrStream.Offset); - HashCombine(Seed, CurrStream.Stride); + auto &CurrStream = Key.Streams[slot]; + if (CurrStream.pBuffer) + { + HashCombine(Seed, CurrStream.pBuffer); + HashCombine(Seed, CurrStream.Offset); + HashCombine(Seed, CurrStream.Stride); + } } + Key.Hash = Seed; } - return Seed; + return Key.Hash; } }; @@ -97,8 +125,13 @@ private: friend class RenderDeviceGLImpl; ThreadingTools::LockFlag m_CacheLockFlag; std::unordered_map m_Cache; - std::unordered_multimap m_PSOToKey; - std::unordered_multimap m_BuffToKey; + std::unordered_multimap m_PSOToKey; + std::unordered_multimap m_BuffToKey; + + // 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; }; } diff --git a/Graphics/GraphicsEngineOpenGL/include/pch.h b/Graphics/GraphicsEngineOpenGL/include/pch.h index 68a1a7e5..f7565490 100644 --- a/Graphics/GraphicsEngineOpenGL/include/pch.h +++ b/Graphics/GraphicsEngineOpenGL/include/pch.h @@ -55,7 +55,7 @@ #include #else #include - #include + #include #endif #endif @@ -70,14 +70,10 @@ #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(); \ diff --git a/Graphics/GraphicsEngineOpenGL/interface/BaseInterfacesGL.h b/Graphics/GraphicsEngineOpenGL/interface/BaseInterfacesGL.h index 7460cc40..cad22936 100644 --- a/Graphics/GraphicsEngineOpenGL/interface/BaseInterfacesGL.h +++ b/Graphics/GraphicsEngineOpenGL/interface/BaseInterfacesGL.h @@ -27,8 +27,7 @@ #include "RenderDeviceGLES.h" namespace Diligent { - static const Diligent::INTERFACE_ID IID_GLDeviceBaseInterface = IID_RenderDeviceGLES; - typedef IRenderDeviceGLES IGLDeviceBaseInterface; + using IGLDeviceBaseInterface = IRenderDeviceGLES; } #endif @@ -36,13 +35,12 @@ #include "RenderDeviceGL.h" namespace Diligent { - static const Diligent::INTERFACE_ID IID_GLDeviceBaseInterface = IID_RenderDeviceGL; - typedef IRenderDeviceGL IGLDeviceBaseInterface; + using IGLDeviceBaseInterface = IRenderDeviceGL; } #endif #include "DeviceContextGL.h" namespace Diligent { - typedef IDeviceContextGL IGLDeviceContextBaseInterface; + using IGLDeviceContextBaseInterface = IDeviceContextGL; } \ No newline at end of file diff --git a/Graphics/GraphicsEngineOpenGL/interface/BufferGL.h b/Graphics/GraphicsEngineOpenGL/interface/BufferGL.h index 6be40c70..eef72890 100644 --- a/Graphics/GraphicsEngineOpenGL/interface/BufferGL.h +++ b/Graphics/GraphicsEngineOpenGL/interface/BufferGL.h @@ -39,7 +39,8 @@ static const Diligent::INTERFACE_ID IID_BufferGL = class IBufferGL : public Diligent::IBuffer { public: - //const GLObjectWrappers::GLBufferObj& GetGLBufferHandle() + /// Returns OpenGL buffer handle + virtual GLuint GetGLBufferHandle() = 0; }; } diff --git a/Graphics/GraphicsEngineOpenGL/interface/DeviceContextGL.h b/Graphics/GraphicsEngineOpenGL/interface/DeviceContextGL.h index 2f8bb330..d2739503 100644 --- a/Graphics/GraphicsEngineOpenGL/interface/DeviceContextGL.h +++ b/Graphics/GraphicsEngineOpenGL/interface/DeviceContextGL.h @@ -39,7 +39,15 @@ static const Diligent::INTERFACE_ID IID_DeviceContextGL = class IDeviceContextGL : public Diligent::IDeviceContext { public: - + + /// Attaches to the active GL context in the thread. + + /// If an application uses multiple GL contexts, this method must be called before any + /// other command to let the engine update active context every time when control flow + /// is passed over from the main application + /// + /// \return false if there is no active GL context, and true otherwise + virtual bool UpdateCurrentGLContext() = 0; }; } diff --git a/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceFactoryOpenGL.h b/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceFactoryOpenGL.h index 3f5dc2aa..8876b9ae 100644 --- a/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceFactoryOpenGL.h +++ b/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceFactoryOpenGL.h @@ -27,7 +27,9 @@ /// Declaration of functions that create OpenGL-based engine implementation #include "RenderDevice.h" +#include "DeviceContext.h" #include "SwapChain.h" +#include "HLSL2GLSLConverter.h" #if defined(PLATFORM_WIN32) || defined(PLATFORM_UNIVERSAL_WINDOWS) @@ -48,22 +50,37 @@ #endif +namespace Diligent +{ + +class IEngineFactoryOpenGL +{ +public: + virtual void CreateDeviceAndSwapChainGL( const EngineCreationAttribs& CreationAttribs, + IRenderDevice **ppDevice, + IDeviceContext **ppImmediateContext, + const SwapChainDesc& SCDesc, + void *pNativeWndHandle, + ISwapChain **ppSwapChain ) = 0; + virtual void CreateHLSL2GLSLConverter(IHLSL2GLSLConverter **ppConverter) = 0; + + virtual void AttachToActiveGLContext( const EngineCreationAttribs& CreationAttribs, + IRenderDevice **ppDevice, + IDeviceContext **ppImmediateContext ) = 0; +}; + +} extern "C" { #if defined(ENGINE_DLL) && (defined(PLATFORM_WIN32) || defined(PLATFORM_UNIVERSAL_WINDOWS)) - typedef void (*CreateDeviceAndSwapChainGLType)( const Diligent::EngineCreationAttribs& CreationAttribs, - Diligent::IRenderDevice **ppDevice, - Diligent::IDeviceContext **ppImmediateContext, - const Diligent::SwapChainDesc& SCDesc, - void *pNativeWndHandle, - Diligent::ISwapChain **ppSwapChain ); + typedef Diligent::IEngineFactoryOpenGL* (*GetEngineFactoryOpenGLType)(); - static void LoadGraphicsEngineOpenGL(CreateDeviceAndSwapChainGLType &CreateDeviceFunc) + static bool LoadGraphicsEngineOpenGL(GetEngineFactoryOpenGLType &GetFactoryFunc) { - CreateDeviceFunc = nullptr; + GetFactoryFunc = nullptr; std::string LibName = "GraphicsEngineOpenGL_"; #if _WIN64 @@ -83,27 +100,23 @@ extern "C" if( hModule == NULL ) { LOG_ERROR_MESSAGE( "Failed to load ", LibName, " library." ); - return; + return false; } - CreateDeviceFunc = reinterpret_cast( GetProcAddress(hModule, "CreateDeviceAndSwapChainGL") ); - if( CreateDeviceFunc == NULL ) + GetFactoryFunc = reinterpret_cast( GetProcAddress(hModule, "GetEngineFactoryOpenGL") ); + if( GetFactoryFunc == NULL ) { - LOG_ERROR_MESSAGE( "Failed to load CreateDeviceAndSwapChainGL() from ", LibName, " library." ); + LOG_ERROR_MESSAGE( "Failed to load GetEngineFactoryOpenGL() from ", LibName, " library." ); FreeLibrary( hModule ); - return; + return false; } + return true; } #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& SCDesc, - void *pNativeWndHandle, - Diligent::ISwapChain **ppSwapChain ); + Diligent::IEngineFactoryOpenGL* GetEngineFactoryOpenGL(); #endif } diff --git a/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGL.h b/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGL.h index 14f59fe0..42e2c979 100644 --- a/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGL.h +++ b/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGL.h @@ -27,6 +27,7 @@ /// Definition of the Diligent::IRenderDeviceGL interface #include "RenderDevice.h" +#include "HLSL2GLSLConverter.h" /// Namespace for the OpenGL implementation of the graphics engine namespace Diligent @@ -40,7 +41,34 @@ static const Diligent::INTERFACE_ID IID_RenderDeviceGL = class IRenderDeviceGL : public IRenderDevice { public: - + + /// Creates a texture from OpenGL handle + + /// \param [in] GLHandle - OpenGL texture handle + /// \param [in] TexDesc - Texture description. The engine can automatically + /// set texture width, height, depth, mip levels count, and format. + /// Remaining fields should be set up by the app. + /// \param [out] ppTexture - Address of the memory location where the pointer to the + /// texture interface will be stored. + /// The function calls AddRef(), so that the new object will contain + /// one refernce. + /// \note Diligent engine texture object does not take ownership of the GL resource, + /// and the application must not destroy it while it is in use by the engine. + virtual void CreateTextureFromGLHandle(Uint32 GLHandle, const TextureDesc &TexDesc, ITexture **ppTexture) = 0; + + /// Creates a buffer from OpenGL handle + + /// \param [in] GLHandle - OpenGL buffer handle + /// \param [in] TexDesc - Buffer description. The engine can automatically + /// recover buffer size, but the rest of the fields need to + /// be set by the client. + /// \param [out] ppBuffer - Address of the memory location where the pointer to the + /// texture interface will be stored. + /// The function calls AddRef(), so that the new object will contain + /// one refernce. + /// \note Diligent engine buffer object does not take ownership of the GL resource, + /// and the application must not destroy it while it is in use by the engine. + virtual void CreateBufferFromGLHandle(Uint32 GLHandle, const BufferDesc &BuffDesc, IBuffer **ppBuffer) = 0; }; } diff --git a/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGLES.h b/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGLES.h index cf667d80..57697d78 100644 --- a/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGLES.h +++ b/Graphics/GraphicsEngineOpenGL/interface/RenderDeviceGLES.h @@ -26,7 +26,7 @@ /// \file /// Definition of the Diligent::IRenderDeviceGLES interface -#include "RenderDevice.h" +#include "RenderDeviceGL.h" #include #include @@ -38,7 +38,7 @@ 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 +class IRenderDeviceGLES : public Diligent::IRenderDeviceGL { public: virtual bool Invalidate() = 0; diff --git a/Graphics/GraphicsEngineOpenGL/interface/TextureGL.h b/Graphics/GraphicsEngineOpenGL/interface/TextureGL.h index c8810052..091e0173 100644 --- a/Graphics/GraphicsEngineOpenGL/interface/TextureGL.h +++ b/Graphics/GraphicsEngineOpenGL/interface/TextureGL.h @@ -39,9 +39,11 @@ static const Diligent::INTERFACE_ID IID_TextureGL = class ITextureGL : public Diligent::ITexture { public: - //const GLObjectWrappers::GLTextureObj& GetGLHandle()const{ return m_GlTexture; } - //GLenum GetBindTarget()const{return m_BindTarget;} + /// Returns OpenGL texture handle + virtual GLuint GetGLTextureHandle() = 0; + /// Returns bind target of the native OpenGL texture + virtual GLenum GetBindTarget()const = 0; }; } diff --git a/Graphics/GraphicsEngineOpenGL/readme.md b/Graphics/GraphicsEngineOpenGL/readme.md new file mode 100644 index 00000000..1831aff0 --- /dev/null +++ b/Graphics/GraphicsEngineOpenGL/readme.md @@ -0,0 +1,112 @@ + +# GraphicsEngineOpenGL + +Implementation of Diligent Engine API using OpenGL/GLES + +# Initialization + +The following code snippet shows how to initialize diligent engine in OpenGL/GLES mode. + +```cpp +#include "RenderDeviceFactoryOpenGL.h" +using namespace Diligent; + +// ... + +#ifdef ENGINE_DLL + GetEngineFactoryOpenGLType GetEngineFactoryOpenGL; + if( !LoadGraphicsEngineOpenGL(GetEngineFactoryOpenGL) ) + return FALSE; +#endif +RefCntAutoPtr pRenderDevice; +RefCntAutoPtr pImmediateContext; +SwapChainDesc SwapChainDesc; +RefCntAutoPtr pSwapChain; +GetEngineFactoryOpenGL()->CreateDeviceAndSwapChainGL( + EngineCreationAttribs(), &pRenderDevice, &pImmediateContext, SwapChainDesc, hWnd, &pSwapChain ); +``` + +Alternatively, the engine can be initialized by attaching to existing OpenGL context (see [below](#initializing-the-engine-by-attaching-to-existing-gl-context)). + +# Interoperability with OpenGL/GLES + +Diligent Engine exposes methods to access internal OpenGL/GLES objects, is able to create diligent engine buffers +and textures from existing GL buffer and texture handles, and can be initialized by attaching to existing GL +context. + +## Accessing Native GL objects + +Below are some of the methods that provide access to internal D3D11 objects: + +| Function | Description | +|---------------------------------------------------|---------------------------------------------------------------------------------------------------------------| +| `GLuint IBufferGL::GetGLBufferHandle()` | returns GL buffer handle | +| `bool IDeviceContextGL::UpdateCurrentGLContext()` | attaches to the active GL context in the thread. Returns false if there is no active context, and true otherwise. If an application uses multiple GL contexts, this method must be called before any other command to let the engine update the active context. | +| `GLuint ITextureGL::GetGLTextureHandle()` | returns GL texture handle | +| `GLenum ITextureGL::GetBindTarget()` | returns GL texture bind target | + +## Creating Diligent Engine Objects from OpenGL Handles + +* `void IRenderDeviceGL::CreateTextureFromGLHandle(Uint32 GLHandle, const TextureDesc &TexDesc, ITexture **ppTexture)` - + creates a diligent engine texture from OpenGL handle. The method takes OpenGL handle GLHandle, texture description TexDesc, + and writes the pointer to the created texture object at the memory address pointed to by ppTexture. The engine can automatically + set texture width, height, depth, mip levels count, and format, but the remaining field of TexDesc structure must be populated by + the application. Note that diligent engine texture object does not take ownership of the GL resource, and the application must + not destroy it while it is in use by the engine. +* `void IRenderDeviceGL::CreateBufferFromGLHandle(Uint32 GLHandle, const BufferDesc &BuffDesc, IBuffer **ppBuffer)` - + creates a diligent engine buffer from OpenGL handle. The method takes OpenGL handle GLHandle, buffer description BuffDesc, + and writes the pointer to the created buffer object at the memory address pointed to by ppBuffer. The engine can automatically + set the buffer size, but the rest of the fields need to be set by the client. Note that diligent engine buffer object does not + take ownership of the GL resource, and the application must not destroy it while it is in use by the engine. + +## Initializing the Engine by Attaching to Existing GL Context + +The code snippet below shows how diligent engine can be attached to existing GL context + +```cpp +auto *pFactoryGL = GetEngineFactoryOpenGL(); +EngineCreationAttribs Attribs; +pFactoryGL->AttachToActiveGLContext(Attribs, &m_Device, &m_Context); +``` + +For more information about interoperability with OpenGL, please visit [Diligent Engine web site](http://diligentgraphics.com/diligent-engine/native-api-interoperability/openglgles-interoperability/) + +# References + +[Diligent Engine](http://diligentgraphics.com/diligent-engine) + +[Interoperability with OpenGL/GLES](http://diligentgraphics.com/diligent-engine/native-api-interoperability/openglgles-interoperability/) + +# Release Notes + +## 2.1 + +### New features + +* Interoperability with OpenGL/GLES + - Accessing GL handles of internal texture/buffer objects + - Createing diligent engine buffers/textures from OpenGL handles + - Attaching to existing OpenGL context +* Integraion with Unity +* Geometry shader support +* Tessellation support +* Support ofr multiple GL contexts: VAO, FBO & Program Pipelines are created and cached for multiple native contexts. + `IDeviceContextGL::UpdateCurrentGLContext()` sets the active GL context in the thread + +### API Changes + +* Updated map interface: removed MAP_WRITE_DISCARD and MAP_WRITE_NO_OVERWRITE map types and added MAP_FLAG_DISCARD and MAP_FLAG_DO_NOT_SYNCHRONIZE flags instead + +## 2.0 + +Reworked the API to follow D3D12 style + +## 1.0 + +Initial release + + + +**Copyright 2015-2017 Egor Yusov** + +[Diligent Graphics](http://diligentgraphics.com) \ No newline at end of file diff --git a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp index e4f148ca..66bc697d 100644 --- a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp @@ -33,30 +33,49 @@ namespace Diligent { -BufferGLImpl::BufferGLImpl(FixedBlockMemoryAllocator &BufferObjMemAllocator, - FixedBlockMemoryAllocator &BuffViewObjMemAllocator, - class RenderDeviceGLImpl *pDeviceGL, - const BufferDesc& BuffDesc, - const BufferData &BuffData /*= BufferData()*/, - bool IsDeviceInternal /*= false*/) : - TBufferBase( BufferObjMemAllocator, BuffViewObjMemAllocator, pDeviceGL, BuffDesc, IsDeviceInternal), - m_GlBuffer(true), // Create buffer immediately - m_uiMapTarget(0), - m_GLUsageHint(0), - m_bUseMapWriteDiscardBugWA(False) +static bool GetUseMapWriteDiscardBugWA(RenderDeviceGLImpl *pDeviceGL) { // 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; + return pDeviceGL->GetGPUInfo().Vendor == GPU_VENDOR::INTEL; +} +static GLenum GetBufferBindTarget(const BufferDesc& Desc) +{ + GLenum Target = GL_ARRAY_BUFFER; + if (Desc.BindFlags & BIND_VERTEX_BUFFER) + Target = GL_ARRAY_BUFFER; + else if(Desc.BindFlags & BIND_INDEX_BUFFER) + Target = GL_ELEMENT_ARRAY_BUFFER; + else if (Desc.BindFlags & BIND_UNIFORM_BUFFER) + Target = GL_UNIFORM_BUFFER; + else if(Desc.BindFlags & BIND_INDIRECT_DRAW_ARGS) + Target = GL_DRAW_INDIRECT_BUFFER; + else if (Desc.Usage == USAGE_CPU_ACCESSIBLE && Desc.CPUAccessFlags == CPU_ACCESS_WRITE) + Target = GL_PIXEL_UNPACK_BUFFER; + + return Target; +} +BufferGLImpl::BufferGLImpl(IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator &BuffViewObjMemAllocator, + RenderDeviceGLImpl *pDeviceGL, + const BufferDesc& BuffDesc, + const BufferData &BuffData /*= BufferData()*/, + bool bIsDeviceInternal) : + TBufferBase( pRefCounters, BuffViewObjMemAllocator, pDeviceGL, BuffDesc, bIsDeviceInternal), + m_GlBuffer(true), // Create buffer immediately + m_uiMapTarget(0), + m_GLUsageHint(UsageToGLUsage(BuffDesc.Usage)), + m_bUseMapWriteDiscardBugWA(GetUseMapWriteDiscardBugWA(pDeviceGL)) +{ if( BuffDesc.Usage == USAGE_STATIC && BuffData.pData == nullptr ) LOG_ERROR_AND_THROW("Static buffer must be initialized with data at creation time"); + auto Target = GetBufferBindTarget(BuffDesc); // 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); + glBindBuffer(Target, 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; @@ -102,17 +121,55 @@ BufferGLImpl::BufferGLImpl(FixedBlockMemoryAllocator &BufferObjMemAllocator, // 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); + glBufferData(Target, DataSize, pData, m_GLUsageHint); CHECK_GL_ERROR_AND_THROW("glBufferData() failed"); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(Target, 0); +} + +static BufferDesc GetBufferDescFromGLHandle(BufferDesc BuffDesc, GLuint BufferHandle) +{ + // NOTE: the operations in this function are merely for debug purposes. + // If binding a buffer to a target does not work, these operations can be skipped + GLenum BindTarget = GetBufferBindTarget(BuffDesc); + + glBindBuffer(BindTarget, BufferHandle); + CHECK_GL_ERROR("Failed to bind GL buffer to ", BindTarget, " target"); + + GLint BufferSize = 0; + glGetBufferParameteriv(BindTarget, GL_BUFFER_SIZE, &BufferSize); + CHECK_GL_ERROR("glGetBufferParameteriv() failed"); + VERIFY_EXPR(BufferSize > 0); + + VERIFY(BuffDesc.uiSizeInBytes == 0 || BuffDesc.uiSizeInBytes == static_cast(BufferSize), "Buffer size specified by the BufferDesc (", BuffDesc.uiSizeInBytes, ") does not match the size recovered from gl buffer object (", BufferSize, ")") + if(BufferSize > 0) + BuffDesc.uiSizeInBytes = static_cast( BufferSize ); + + glBindBuffer(BindTarget, 0); + CHECK_GL_ERROR("Failed to unbind GL buffer"); + + return BuffDesc; +} + +BufferGLImpl::BufferGLImpl(IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator &BuffViewObjMemAllocator, + RenderDeviceGLImpl *pDeviceGL, + const BufferDesc& BuffDesc, + GLuint GLHandle, + bool bIsDeviceInternal) : + TBufferBase( pRefCounters, BuffViewObjMemAllocator, pDeviceGL, GetBufferDescFromGLHandle(BuffDesc, GLHandle), bIsDeviceInternal), + // Attach to external buffer handle + m_GlBuffer(true, GLObjectWrappers::GLBufferObjCreateReleaseHelper(GLHandle)), + m_uiMapTarget(0), + m_GLUsageHint(UsageToGLUsage(BuffDesc.Usage)), + m_bUseMapWriteDiscardBugWA(GetUseMapWriteDiscardBugWA(pDeviceGL)) +{ } BufferGLImpl::~BufferGLImpl() { - static_cast( static_cast( GetDevice() ) )->m_VAOCache.OnDestroyBuffer(this); + static_cast( GetDevice() )->OnDestroyBuffer(this); } IMPLEMENT_QUERY_INTERFACE( BufferGLImpl, IID_BufferGL, TBufferBase ) @@ -200,48 +257,51 @@ void BufferGLImpl :: Map(IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapF 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 ) + + if (MapFlags & MAP_FLAG_DISCARD) { - // 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; + 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; + } } - 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; + if (MapFlags & MAP_FLAG_DO_NOT_SYNCHRONIZE) + { + // If GL_MAP_UNSYNCHRONIZED_BIT flag is set, OpenGL will not attempt to synchronize + // operations on the buffer. + Access |= GL_MAP_UNSYNCHRONIZED_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; + case MAP_READ_WRITE: + Access |= GL_MAP_WRITE_BIT | GL_MAP_READ_BIT; break; + default: UNEXPECTED( "Unknown map type" ); } @@ -251,9 +311,9 @@ void BufferGLImpl :: Map(IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapF glBindBuffer(m_uiMapTarget, 0); } -void BufferGLImpl::Unmap( IDeviceContext *pContext, MAP_TYPE MapType ) +void BufferGLImpl::Unmap( IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapFlags ) { - TBufferBase::Unmap(pContext, MapType); + TBufferBase::Unmap(pContext, MapType, MapFlags); glBindBuffer(m_uiMapTarget, m_GlBuffer); auto Result = glUnmapBuffer(m_uiMapTarget); @@ -307,7 +367,7 @@ void BufferGLImpl::CreateViewInternal( const BufferViewDesc &OrigViewDesc, class auto pContext = pDeviceGLImpl->GetImmediateContext(); VERIFY( pContext, "Immediate context has been released" ); - *ppView = NEW(BuffViewAllocator, "BufferViewGLImpl instance", BufferViewGLImpl, pDeviceGLImpl, pContext, ViewDesc, this, bIsDefaultView ); + *ppView = NEW_RC_OBJ(BuffViewAllocator, "BufferViewGLImpl instance", BufferViewGLImpl, bIsDefaultView ? this : nullptr)(pDeviceGLImpl, pContext, ViewDesc, this, bIsDefaultView); if( !bIsDefaultView ) (*ppView)->AddRef(); diff --git a/Graphics/GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp index ad598f97..f0c5a727 100644 --- a/Graphics/GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp @@ -31,16 +31,16 @@ namespace Diligent { - BufferViewGLImpl::BufferViewGLImpl( FixedBlockMemoryAllocator& BuffViewObjAllocator, + BufferViewGLImpl::BufferViewGLImpl( IReferenceCounters *pRefCounters, IRenderDevice *pDevice, IDeviceContext *pContext, const BufferViewDesc& ViewDesc, BufferGLImpl* pBuffer, bool bIsDefaultView) : - TBuffViewBase(BuffViewObjAllocator, pDevice, ViewDesc, pBuffer, bIsDefaultView ), + TBuffViewBase(pRefCounters, pDevice, ViewDesc, pBuffer, bIsDefaultView ), m_GLTexBuffer(false) { - if( ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE ) + if( ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE && pBuffer->GetDesc().Mode == BUFFER_MODE_FORMATTED ) { auto *pContextGL = ValidatedCast(pContext); auto &ContextState = pContextGL->GetContextState(); @@ -49,8 +49,9 @@ namespace Diligent ContextState.BindTexture(-1, GL_TEXTURE_BUFFER, m_GLTexBuffer ); const auto &BuffFmt = pBuffer->GetDesc().Format; + VERIFY_EXPR(BuffFmt.ValueType != VT_UNDEFINED) auto GLFormat = TypeToGLTexFormat( BuffFmt.ValueType, BuffFmt.NumComponents, BuffFmt.IsNormalized ); - glTexBuffer( GL_TEXTURE_BUFFER, GLFormat, pBuffer->GetGLBufferHandle() ); + glTexBuffer( GL_TEXTURE_BUFFER, GLFormat, pBuffer->GetGLHandle() ); CHECK_GL_ERROR_AND_THROW( "Failed to create texture buffer" ); ContextState.BindTexture(-1, GL_TEXTURE_BUFFER, GLObjectWrappers::GLTextureObj(false) ); diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp index 6077b027..21953d10 100644 --- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp @@ -48,22 +48,13 @@ using namespace std; namespace Diligent { - DeviceContextGLImpl::DeviceContextGLImpl( IMemoryAllocator &RawMemAllocator, class RenderDeviceGLImpl *pDeviceGL, bool bIsDeferred ) : - TDeviceContextBase(RawMemAllocator, pDeviceGL, bIsDeferred), + DeviceContextGLImpl::DeviceContextGLImpl( IReferenceCounters *pRefCounters, class RenderDeviceGLImpl *pDeviceGL, bool bIsDeferred ) : + TDeviceContextBase(pRefCounters, pDeviceGL, bIsDeferred), m_ContextState(pDeviceGL), m_CommitedResourcesTentativeBarriers(0) { 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 ) @@ -74,7 +65,6 @@ namespace Diligent TDeviceContextBase::SetPipelineState(pPipelineState); const auto &Desc = pPipelineState->GetDesc(); - auto *pPipelineStateGL = ValidatedCast(pPipelineState); if (Desc.IsComputePipeline) { } @@ -174,10 +164,14 @@ namespace Diligent m_bVAOIsUpToDate = false; } - void DeviceContextGLImpl::ClearState() + void DeviceContextGLImpl::InvalidateState() { - TDeviceContextBase::ClearState(); + TDeviceContextBase::InvalidateState(); + m_ContextState.Invalidate(); + m_BoundWritableTextures.clear(); + m_BoundWritableBuffers.clear(); + m_bVAOIsUpToDate = false; } void DeviceContextGLImpl::SetIndexBuffer( IBuffer *pIndexBuffer, Uint32 ByteOffset ) @@ -287,24 +281,33 @@ namespace Diligent } } - void DeviceContextGLImpl::RebindRenderTargets() + void DeviceContextGLImpl::CommitRenderTargets() { - Uint32 NumRenderTargets = m_NumBoundRenderTargets; - 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]; + if (m_IsDefaultFramebufferBound) + { + m_ContextState.BindFBO( GLObjectWrappers::GLFrameBufferObj(false) ); + } + else + { + VERIFY(m_NumBoundRenderTargets != 0 || m_pBoundDepthStencil, "At least one render target or a depth stencil is expected" ) - auto *pRenderDeviceGL = ValidatedCast(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 ); + Uint32 NumRenderTargets = m_NumBoundRenderTargets; + 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(m_pDevice.RawPtr()); + auto CurrentNativeGLContext = m_ContextState.GetCurrentGLContext(); + auto &FBOCache = pRenderDeviceGL->GetFBOCache(CurrentNativeGLContext); + 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); } @@ -312,7 +315,7 @@ namespace Diligent void DeviceContextGLImpl::SetRenderTargets( Uint32 NumRenderTargets, ITextureView *ppRenderTargets[], ITextureView *pDepthStencil ) { if( TDeviceContextBase::SetRenderTargets( NumRenderTargets, ppRenderTargets, pDepthStencil ) ) - RebindRenderTargets(); + CommitRenderTargets(); } void DeviceContextGLImpl::BindProgramResources( Uint32 &NewMemoryBarriers, IShaderResourceBinding *pResBinding ) @@ -328,7 +331,7 @@ namespace Diligent const auto &DeviceCaps = pRenderDeviceGL->GetDeviceCaps(); auto &Prog = pPipelineStateGL->GetGLProgram(); - auto &Pipeline = pPipelineStateGL->GetGLProgramPipeline(); + auto &Pipeline = pPipelineStateGL->GetGLProgramPipeline( m_ContextState.GetCurrentGLContext() ); VERIFY( Prog ^ Pipeline, "Only one of program or pipeline can be specified" ); if( !(Prog || Pipeline) ) { @@ -559,7 +562,7 @@ namespace Diligent { auto *pBufferViewOGL = ValidatedCast(Resource.RawPtr()); const auto &ViewDesc = pBufferViewOGL->GetDesc(); - VERIFY( ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Incorrect buffer view type" ); + VERIFY( ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS || ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Unexpceted buffer view type" ); auto *pBuffer = pBufferViewOGL->GetBuffer(); CHECK_DYNAMIC_TYPE( BufferGLImpl, pBuffer ); @@ -573,7 +576,8 @@ namespace Diligent glBindBufferRange( GL_SHADER_STORAGE_BUFFER, it->Binding + ArrInd, pBufferOGL->m_GlBuffer, ViewDesc.ByteOffset, ViewDesc.ByteWidth ); CHECK_GL_ERROR( "Failed to bind shader storage buffer" ); - m_BoundWritableBuffers.push_back( pBufferOGL ); + if( ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS ) + m_BoundWritableBuffers.push_back( pBufferOGL ); } else { @@ -646,14 +650,15 @@ namespace Diligent return; } + auto *pRenderDeviceGL = ValidatedCast(m_pDevice.RawPtr()); + auto CurrNativeGLContext = pRenderDeviceGL->m_GLContext.GetCurrentNativeGLContext(); if(!m_bVAOIsUpToDate) { - auto *pRenderDeviceGL = ValidatedCast(m_pDevice.RawPtr()); - if( m_pPipelineState->GetDesc().GraphicsPipeline.InputLayout.NumElements > 0 ) + auto &VAOCache = pRenderDeviceGL->GetVAOCache(CurrNativeGLContext); + IBuffer *pIndexBuffer = DrawAttribs.IsIndexed ? m_pIndexBuffer.RawPtr() : nullptr; + if( m_pPipelineState->GetDesc().GraphicsPipeline.InputLayout.NumElements > 0 || pIndexBuffer != nullptr) { - IBuffer *pIndexBuffer = DrawAttribs.IsIndexed ? m_pIndexBuffer.RawPtr() : nullptr; - auto &VAOCache = pRenderDeviceGL->m_VAOCache; - const auto& VAO = VAOCache.GetVAO( m_pPipelineState.RawPtr(), pIndexBuffer, m_VertexStreams, m_NumVertexStreams, m_ContextState ); + const auto& VAO = VAOCache.GetVAO( m_pPipelineState, pIndexBuffer, m_VertexStreams, m_NumVertexStreams, m_ContextState ); m_ContextState.BindVAO( VAO ); } else @@ -661,12 +666,23 @@ namespace Diligent // 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 ); + const auto& VAO = VAOCache.GetEmptyVAO(); + m_ContextState.BindVAO( VAO ); } m_bVAOIsUpToDate = true; } - auto GlTopology = PrimitiveTopologyToGLTopology( DrawAttribs.Topology ); + GLenum GlTopology; + if (DrawAttribs.Topology >= PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST) + { + GlTopology = GL_PATCHES; + auto NumVertices = static_cast(DrawAttribs.Topology - PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + 1); + m_ContextState.SetNumPatchVertices(NumVertices); + } + else + { + GlTopology = PrimitiveTopologyToGLTopology( DrawAttribs.Topology ); + } GLenum IndexType = 0; Uint32 FirstIndexByteOffset = 0; if( DrawAttribs.IsIndexed ) @@ -830,7 +846,6 @@ namespace Diligent 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(pView); if( pView != m_pBoundDepthStencil ) { UNEXPECTED( "Depth stencil buffer being cleared is not bound to the pipeline" ); @@ -839,7 +854,7 @@ namespace Diligent } else { - if( !(nullptr == m_pBoundDepthStencil && m_NumBoundRenderTargets == 0) ) + if( !m_IsDefaultFramebufferBound ) { 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" ); @@ -876,7 +891,6 @@ namespace Diligent 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(pView); for( Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt ) if( m_pBoundRenderTargets[rt] == pView ) { @@ -892,7 +906,7 @@ namespace Diligent } else { - if( m_NumBoundRenderTargets == 0 && m_pBoundDepthStencil == nullptr ) + if( m_IsDefaultFramebufferBound ) RTIndex = 0; else { @@ -942,4 +956,14 @@ namespace Diligent LOG_ERROR("Deferred contexts are not supported in OpenGL mode"); } + bool DeviceContextGLImpl::UpdateCurrentGLContext() + { + auto *pRenderDeviceGL = ValidatedCast(m_pDevice.RawPtr()); + auto NativeGLContext = pRenderDeviceGL->m_GLContext.GetCurrentNativeGLContext(); + if (NativeGLContext == NULL) + return false; + + m_ContextState.SetCurrentGLContext(NativeGLContext); + return true; + } } diff --git a/Graphics/GraphicsEngineOpenGL/src/FBOCache.cpp b/Graphics/GraphicsEngineOpenGL/src/FBOCache.cpp index f697ae26..74d608eb 100644 --- a/Graphics/GraphicsEngineOpenGL/src/FBOCache.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/FBOCache.cpp @@ -105,19 +105,15 @@ void FBOCache::OnReleaseTexture(ITexture *pTexture) } const GLObjectWrappers::GLFrameBufferObj& FBOCache::GetFBO( Uint32 NumRenderTargets, - ITextureView *ppRenderTargets[], - ITextureView *pDepthStencil, - GLContextState &ContextState ) + 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; - } + VERIFY(NumRenderTargets != 0 || pDepthStencil != nullptr, "At least one render target or a depth-stencil buffer must be provided"); // Lock the cache ThreadingTools::LockHelper CacheLock(m_CacheLockFlag); @@ -262,15 +258,15 @@ const GLObjectWrappers::GLFrameBufferObj& FBOCache::GetFBO( Uint32 NumRenderTarg UNEXPECTED( "Framebuffer is incomplete" ); } - auto NewElems = m_Cache.emplace( make_pair(Key, std::move(NewFBO)) ); + auto NewElems = m_Cache.emplace( std::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) ); + m_TexIdToKey.insert( std::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) ); + m_TexIdToKey.insert( std::make_pair(Key.RTIds[rt], Key) ); } return NewElems.first->second; diff --git a/Graphics/GraphicsEngineOpenGL/src/GLContextAndroid.cpp b/Graphics/GraphicsEngineOpenGL/src/GLContextAndroid.cpp index 0a8b0442..3bafe954 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLContextAndroid.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLContextAndroid.cpp @@ -54,23 +54,23 @@ namespace Diligent * Below, we select an EGLConfig with at least 8 bits per color * component compatible with on-screen windows */ + color_size_ = 8; + depth_size_ = 24; 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_BLUE_SIZE, color_size_, + EGL_GREEN_SIZE, color_size_, + EGL_RED_SIZE, color_size_, + EGL_ALPHA_SIZE, color_size_, + EGL_DEPTH_SIZE, depth_size_, //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 ); @@ -82,15 +82,16 @@ namespace Diligent if( !num_configs ) { //Fall back to 16bit depth buffer + depth_size_ = 16; 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_BLUE_SIZE, color_size_, + EGL_GREEN_SIZE, color_size_, + EGL_RED_SIZE, color_size_, + EGL_ALPHA_SIZE, color_size_, + EGL_DEPTH_SIZE, depth_size_, EGL_NONE }; success = eglChooseConfig( display_, attribs, &config_, 1, &num_configs ); @@ -98,8 +99,6 @@ namespace Diligent { LOG_ERROR_AND_THROW( "Failed to choose 16-bit depth config" ); } - - depth_size_ = 16; } if( !num_configs ) @@ -107,6 +106,8 @@ namespace Diligent LOG_ERROR_AND_THROW( "Unable to retrieve EGL config" ); } + LOG_INFO_MESSAGE("Chosen EGL config: ", color_size_, " bit color, ", depth_size_, " bit depth"); + surface_ = eglCreateWindowSurface( display_, config_, window_, NULL ); if( surface_ == EGL_NO_SURFACE ) { @@ -127,8 +128,6 @@ namespace Diligent eglGetConfigAttrib( display_, config_, EGL_NATIVE_VISUAL_ID, &format ); ANativeWindow_setBuffersGeometry( window_, 0, 0, format ); - LoadGLFunctions(); - return true; } @@ -162,6 +161,22 @@ namespace Diligent return true; } + void GLContext::AttachToCurrentEGLContext() + { + if( eglGetCurrentContext() == EGL_NO_CONTEXT ) + { + LOG_ERROR_AND_THROW( "Failed to attach to EGLContext: no active context" ); + } + context_valid_ = true; + glGetIntegerv( GL_MAJOR_VERSION, &major_version_ ); + glGetIntegerv( GL_MINOR_VERSION, &minor_version_ ); + } + + GLContext::NativeGLContextType GLContext::GetCurrentNativeGLContext() + { + return eglGetCurrentContext(); + } + void GLContext::InitGLES() { if( gles_initialized_ ) @@ -169,21 +184,23 @@ namespace Diligent // //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." ) + LOG_INFO_MESSAGE( "GL Version: ", versionStr, '\n' ); + #if USE_GL3_STUB - && gl3stubInit() + gl3stubInit(); #endif - ) - { - es3_supported_ = true; - gl_version_ = 3.0f; - } - else - { - gl_version_ = 2.0f; - } + + LoadGLFunctions(); + + // 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"); gles_initialized_ = true; } @@ -197,8 +214,15 @@ namespace Diligent //Initialize EGL // window_ = window; - InitEGLSurface(); - InitEGLContext(); + if (window != nullptr) + { + InitEGLSurface(); + InitEGLContext(); + } + else + { + AttachToCurrentEGLContext(); + } InitGLES(); egl_context_initialized_ = true; @@ -210,7 +234,6 @@ namespace Diligent 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), @@ -380,7 +403,7 @@ namespace Diligent DeviceCaps.DevType = DeviceType::OpenGLES; DeviceCaps.MajorVersion = major_version_; DeviceCaps.MinorVersion = minor_version_; - bool IsGLES31OrAbove = (major_version_ >= 4 || major_version_ == 3 && minor_version_ >= 1); + bool IsGLES31OrAbove = (major_version_ >= 4 || (major_version_ == 3 && minor_version_ >= 1) ); DeviceCaps.bSeparableProgramSupported = IsGLES31OrAbove; DeviceCaps.bIndirectRenderingSupported = IsGLES31OrAbove; diff --git a/Graphics/GraphicsEngineOpenGL/src/GLContextState.cpp b/Graphics/GraphicsEngineOpenGL/src/GLContextState.cpp index d7e38217..6fab02ba 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLContextState.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLContextState.cpp @@ -36,16 +36,7 @@ using namespace Diligent; namespace Diligent { - GLContextState::GLContextState( RenderDeviceGLImpl *pDeviceGL ) : - m_PendingMemoryBarriers( 0 ), - m_DepthCmpFunc( COMPARISON_FUNC_UNKNOWN ), - m_StencilReadMask( 0xFF ), - m_StencilWriteMask( 0xFF ), - m_GLProgId( 0 ), - m_GLPipelineId( 0 ), - m_VAOId( 0 ), - m_FBOId( 0 ), - m_iActiveTexture(-1) + GLContextState::GLContextState( RenderDeviceGLImpl *pDeviceGL ) { const DeviceCaps &DeviceCaps = pDeviceGL->GetDeviceCaps(); m_Caps.bFillModeSelectionSupported = DeviceCaps.bWireframeFillSupported; @@ -59,10 +50,52 @@ namespace Diligent m_BoundTextures.reserve( m_Caps.m_iMaxCombinedTexUnits ); m_BoundSamplers.reserve( 32 ); - m_pBoundImages.reserve( 32 ); + m_BoundImages.reserve( 32 ); + + Invalidate(); + + m_CurrentGLContext = pDeviceGL->m_GLContext.GetCurrentNativeGLContext(); + } + + void GLContextState::Invalidate() + { +#if !defined(PLATFORM_ANDROID) + // On Android this results in OpenGL error, so we will not + // clear the barriers. All the required barriers will be + // executed next frame when needed + if(m_PendingMemoryBarriers != 0) + EnsureMemoryBarrier(m_PendingMemoryBarriers); + m_PendingMemoryBarriers = 0; +#endif + + // Unity messes up at least VAO left in the context, + // so unbid what we bound + glUseProgram( 0 ); + glBindProgramPipeline( 0 ); + glBindVertexArray( 0 ); + glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 ); + glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 ); + CHECK_GL_ERROR( "Failed to reset GL context state" ); + + m_GLProgId = -1; + m_GLPipelineId = -1; + m_VAOId = -1; + m_FBOId = -1; + + m_BoundTextures.clear(); + m_BoundSamplers.clear(); + m_BoundImages.clear(); + + m_DSState = DepthStencilGLState(); + m_RSState = RasterizerGLState(); for( Uint32 rt = 0; rt < _countof( m_ColorWriteMasks ); ++rt ) - m_ColorWriteMasks[rt] = COLOR_MASK_ALL; + m_ColorWriteMasks[rt] = 0xFF; + + m_bIndependentWriteMasks = EnableStateHelper(); + + m_iActiveTexture = -1; + m_NumPatchVertices = -1; } template @@ -142,7 +175,7 @@ namespace Diligent bool UpdateBoundObjectsArr( std::vector< UniqueIdentifier >& BoundObjectIDs, Uint32 Index, const ObjectType &NewObject, GLuint &NewGLHandle ) { if( Index >= BoundObjectIDs.size() ) - BoundObjectIDs.resize( Index + 1 ); + BoundObjectIDs.resize( Index + 1, -1 ); return UpdateBoundObject( BoundObjectIDs[Index], NewObject, NewGLHandle ); } @@ -208,11 +241,11 @@ namespace Diligent Access, Format ); - if( Index >= m_pBoundImages.size() ) - m_pBoundImages.resize( Index + 1 ); - if( !(m_pBoundImages[Index] == NewImageInfo) ) + if( Index >= m_BoundImages.size() ) + m_BoundImages.resize( Index + 1 ); + if( !(m_BoundImages[Index] == NewImageInfo) ) { - m_pBoundImages[Index] = NewImageInfo; + m_BoundImages[Index] = NewImageInfo; GLint GLTexHandle = pTexView->GetHandle(); glBindImageTexture( Index, GLTexHandle, MipLevel, IsLayered, Layer, Access, Format ); CHECK_GL_ERROR( "glBindImageTexture() failed" ); @@ -271,7 +304,7 @@ namespace Diligent void GLContextState::EnableDepthTest( bool bEnable ) { - if( m_DepthEnableState != bEnable ) + if( m_DSState.m_DepthEnableState != bEnable ) { if( bEnable ) { @@ -283,35 +316,35 @@ namespace Diligent glDisable( GL_DEPTH_TEST ); CHECK_GL_ERROR( "Failed to disable detph test" ); } - m_DepthEnableState = bEnable; + m_DSState.m_DepthEnableState = bEnable; } } void GLContextState::EnableDepthWrites( bool bEnable ) { - if( m_DepthWritesEnableState != bEnable ) + if( m_DSState.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; + m_DSState.m_DepthWritesEnableState = bEnable; } } void GLContextState::SetDepthFunc( COMPARISON_FUNCTION CmpFunc ) { - if( m_DepthCmpFunc != CmpFunc ) + if( m_DSState.m_DepthCmpFunc != CmpFunc ) { auto GlCmpFunc = CompareFuncToGLCompareFunc( CmpFunc ); glDepthFunc( GlCmpFunc ); CHECK_GL_ERROR( "Failed to set GL comparison function" ); - m_DepthCmpFunc = CmpFunc; + m_DSState.m_DepthCmpFunc = CmpFunc; } } void GLContextState::EnableStencilTest( bool bEnable ) { - if( m_StencilTestEnableState != bEnable ) + if( m_DSState.m_StencilTestEnableState != bEnable ) { if( bEnable ) { @@ -323,22 +356,22 @@ namespace Diligent glDisable( GL_STENCIL_TEST ); CHECK_GL_ERROR( "Failed to disable stencil test" ); } - m_StencilTestEnableState = bEnable; + m_DSState.m_StencilTestEnableState = bEnable; } } void GLContextState::SetStencilWriteMask( Uint8 StencilWriteMask ) { - if( m_StencilWriteMask != StencilWriteMask ) + if( m_DSState.m_StencilWriteMask != StencilWriteMask ) { glStencilMask( StencilWriteMask ); - m_StencilWriteMask = StencilWriteMask; + m_DSState.m_StencilWriteMask = StencilWriteMask; } } void GLContextState::SetStencilRef(GLenum Face, Int32 Ref) { - auto& FaceStencilOp = m_StencilOpState[Face == GL_FRONT ? 0 : 1]; + auto& FaceStencilOp = m_DSState.m_StencilOpState[Face == GL_FRONT ? 0 : 1]; auto GlStencilFunc = CompareFuncToGLCompareFunc( FaceStencilOp.Func ); glStencilFuncSeparate( Face, GlStencilFunc, Ref, FaceStencilOp.Mask ); CHECK_GL_ERROR( "Failed to set stencil function" ); @@ -346,7 +379,7 @@ namespace Diligent void GLContextState::SetStencilFunc( GLenum Face, COMPARISON_FUNCTION Func, Int32 Ref, Uint32 Mask ) { - auto& FaceStencilOp = m_StencilOpState[Face == GL_FRONT ? 0 : 1]; + auto& FaceStencilOp = m_DSState.m_StencilOpState[Face == GL_FRONT ? 0 : 1]; if( FaceStencilOp.Func != Func || FaceStencilOp.Ref != Ref || FaceStencilOp.Mask != Mask ) @@ -361,7 +394,7 @@ namespace Diligent void GLContextState::SetStencilOp( GLenum Face, STENCIL_OP StencilFailOp, STENCIL_OP StencilDepthFailOp, STENCIL_OP StencilPassOp ) { - auto& FaceStencilOp = m_StencilOpState[Face == GL_FRONT ? 0 : 1]; + auto& FaceStencilOp = m_DSState.m_StencilOpState[Face == GL_FRONT ? 0 : 1]; if( FaceStencilOp.StencilFailOp != StencilFailOp || FaceStencilOp.StencilDepthFailOp != StencilDepthFailOp || FaceStencilOp.StencilPassOp != StencilPassOp ) @@ -463,6 +496,8 @@ namespace Diligent { if( bEnableDepthClamp ) { +#pragma warning(push) +#pragma warning(disable : 4127) if( GL_DEPTH_CLAMP ) { glEnable( GL_DEPTH_CLAMP ); @@ -483,6 +518,7 @@ namespace Diligent { LOG_WARNING_MESSAGE( "Disabling depth clamp is not supported" ) } +#pragma warning(pop) } m_RSState.DepthClampEnable = bEnableDepthClamp; } @@ -515,7 +551,7 @@ namespace Diligent void GLContextState::SetBlendState( const BlendStateDesc &BSDsc, Uint32 SampleMask ) { - VERIFY(SampleMask = 0xFFFFFFFF, "Sample mask is not currently implemented in GL"); + VERIFY(SampleMask == 0xFFFFFFFF, "Sample mask is not currently implemented in GL"); bool bEnableBlend = false; if( BSDsc.IndependentBlendEnable ) @@ -655,4 +691,14 @@ namespace Diligent WriteMask = m_ColorWriteMasks[ RTIndex ]; bIsIndependent = m_bIndependentWriteMasks; } + + void GLContextState::SetNumPatchVertices(Int32 NumVertices) + { + if (NumVertices != m_NumPatchVertices) + { + m_NumPatchVertices = NumVertices; + glPatchParameteri(GL_PATCH_VERTICES, static_cast(NumVertices)); + CHECK_GL_ERROR( "Failed to set the number of patch vertices" ); + } + } } diff --git a/Graphics/GraphicsEngineOpenGL/src/GLContextWindows.cpp b/Graphics/GraphicsEngineOpenGL/src/GLContextWindows.cpp index 3cdbd005..da2367f1 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLContextWindows.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLContextWindows.cpp @@ -36,7 +36,7 @@ namespace Diligent GLenum severity, GLsizei length, const GLchar* message, - void* userParam ) + const void* userParam ) { std::stringstream MessageSS; @@ -129,7 +129,6 @@ namespace Diligent GLenum err = glewInit(); if( GLEW_OK != err ) LOG_ERROR_AND_THROW( "Failed to initialize GLEW" ); - if( wglewIsSupported( "WGL_ARB_create_context" ) == 1 ) { @@ -145,9 +144,9 @@ namespace Diligent 0, 0 }; - #ifdef _DEBUG +#ifdef _DEBUG attribs[5] |= WGL_CONTEXT_DEBUG_BIT_ARB; - #endif +#endif // Create new rendering context // In order to create new OpenGL rendering context we have to call function wglCreateContextAttribsARB(), @@ -159,24 +158,32 @@ namespace Diligent // Delete tempContext wglMakeCurrent( NULL, NULL ); wglDeleteContext( tempContext ); - // + // Make new context current 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) + { //It's not possible to make a GL 4.x context. Use the old style context (GL 2.1 and before) m_Context = tempContext; } + + 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 ); + } } else { auto CurrentCtx = wglGetCurrentContext(); - m_WindowHandleToDeviceContext = wglGetCurrentDC(); - if (CurrentCtx != 0) - { - LOG_INFO_MESSAGE("Attaching to existing OpenGL context") - } - else + if (CurrentCtx == 0) { LOG_ERROR_AND_THROW("No current GL context found! Provide non-null handle to a native Window to create a GL context") } @@ -193,19 +200,7 @@ namespace Diligent //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 ); - } + LOG_INFO_MESSAGE(Info.pNativeWndHandle != nullptr ? "Initialized OpenGL " : "Attached to OpenGL ", MajorVersion, '.', MinorVersion, " context (", GLVersionString, ')') // Under the standard filtering rules for cubemaps, filtering does not work across faces of the cubemap. // This results in a seam across the faces of a cubemap. This was a hardware limitation in the past, but @@ -215,6 +210,15 @@ namespace Diligent if( glGetError() != GL_NO_ERROR ) LOG_ERROR_MESSAGE("Failed to enable seamless cubemap filtering"); + // 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"); + DeviceCaps.DevType = DeviceType::OpenGL; DeviceCaps.MajorVersion = MajorVersion; DeviceCaps.MinorVersion = MinorVersion; @@ -229,7 +233,7 @@ namespace Diligent GLContext::~GLContext() { - // Do not destroy context if it was create by the app. + // Do not destroy context if it was created by the app. if( m_Context ) { wglMakeCurrent( m_WindowHandleToDeviceContext, 0 ); @@ -239,6 +243,14 @@ namespace Diligent void GLContext::SwapBuffers() { - ::SwapBuffers( m_WindowHandleToDeviceContext ); + if(m_WindowHandleToDeviceContext) + ::SwapBuffers( m_WindowHandleToDeviceContext ); + else + LOG_ERROR("Swap buffer failed because window handle to device context is not initialized") + } + + GLContext::NativeGLContextType GLContext::GetCurrentNativeGLContext() + { + return wglGetCurrentContext(); } } diff --git a/Graphics/GraphicsEngineOpenGL/src/GLProgramResources.cpp b/Graphics/GraphicsEngineOpenGL/src/GLProgramResources.cpp index b3978069..e7538949 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLProgramResources.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLProgramResources.cpp @@ -432,13 +432,17 @@ namespace Diligent RefCntAutoPtr pNewRes; pResourceMapping->GetResource( Name.c_str(), static_cast(&pNewRes), ArrInd ); - if( !pNewRes ) + if (pNewRes != nullptr) { - if( Flags & BIND_SHADER_RESOURCES_ALL_RESOLVED ) - LOG_ERROR_MESSAGE( "Resource \"", Name, "\" is not found in the resource mapping" ); - continue; + if(res->VarType == SHADER_VARIABLE_TYPE_STATIC && CurrResource != nullptr && CurrResource != pNewRes ) + LOG_ERROR_MESSAGE( "Updating binding for static variable \"", Name, "\" is invalid and may result in an undefined behavior" ); + CurrResource = pNewRes; + } + else + { + if ( CurrResource == nullptr && (Flags & BIND_SHADER_RESOURCES_ALL_RESOLVED) ) + LOG_ERROR_MESSAGE("Resource \"", Name, "\" is not found in the resource mapping"); } - CurrResource = pNewRes; } } } @@ -460,7 +464,6 @@ namespace Diligent { for( auto res = ResArr.begin(); res != ResArr.end(); ++res ) { - auto &Name = res->Name; for(Uint32 ArrInd = 0; ArrInd < res->pResources.size(); ++ArrInd) { if( !res->pResources[ArrInd] ) diff --git a/Graphics/GraphicsEngineOpenGL/src/GLStubs.cpp b/Graphics/GraphicsEngineOpenGL/src/GLStubs.cpp index 5a0ff686..ce2c4d61 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLStubs.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLStubs.cpp @@ -144,6 +144,15 @@ 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 +#ifdef LOAD_GL_PATCH_PARAMTER_I + DECLARE_GL_FUNCTION( glPatchParameteri, PFNGLPATCHPARAMETERIPROC, GLenum pname, GLint value ) +#endif + +#ifdef LOAD_GET_TEX_LEVEL_PARAMETER_IV + DECLARE_GL_FUNCTION( glGetTexLevelParameteriv, PFNGLGETTEXLEVELPARAMETERIVPROC, GLenum target, GLint level, GLenum pname, GLint *params ) +#endif + + void LoadGLFunctions() { @@ -261,6 +270,14 @@ Func = (FuncType)eglGetProcAddress( #Func );\ #ifdef LOAD_GL_COPY_IMAGE_SUB_DATA // Do not use proxy if function is not available! - glCopyImageSubData = (PFNGLCOPYIMAGESUBDATAPROC)eglGetProcAddress( "glCopyImageSubData" ); + LOAD_GL_FUNCTION(glCopyImageSubData, PFNGLCOPYIMAGESUBDATAPROC) +#endif + +#ifdef LOAD_GL_PATCH_PARAMTER_I + LOAD_GL_FUNCTION(glPatchParameteri, PFNGLPATCHPARAMETERIPROC) +#endif + +#ifdef LOAD_GET_TEX_LEVEL_PARAMETER_IV + LOAD_GL_FUNCTION(glGetTexLevelParameteriv, PFNGLGETTEXLEVELPARAMETERIVPROC) #endif } diff --git a/Graphics/GraphicsEngineOpenGL/src/GLTypeConversions.cpp b/Graphics/GraphicsEngineOpenGL/src/GLTypeConversions.cpp index d67f75cb..cafb7a3c 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLTypeConversions.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLTypeConversions.cpp @@ -23,143 +23,153 @@ #include "pch.h" #include "GLTypeConversions.h" +#include "GraphicsUtilities.h" namespace Diligent { - -GLenum TexFormatToGLInternalTexFormat(TEXTURE_FORMAT TexFormat, Uint32 BindFlags) +class FormatToGLInternalTexFormatMap { - static Bool bFormatMapIntialized = false; - static GLenum FmtToGLFmtMap[TEX_FORMAT_NUM_FORMATS] = {0}; - if( !bFormatMapIntialized ) +public: + FormatToGLInternalTexFormatMap() { // 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; + m_FmtToGLFmtMap[ TEX_FORMAT_UNKNOWN ] = 0; + + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA32_TYPELESS ] = GL_RGBA32F; + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA32_FLOAT ] = GL_RGBA32F; + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA32_UINT ] = GL_RGBA32UI; + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA32_SINT ] = GL_RGBA32I; + + m_FmtToGLFmtMap[ TEX_FORMAT_RGB32_TYPELESS ] = GL_RGB32F; + m_FmtToGLFmtMap[ TEX_FORMAT_RGB32_FLOAT ] = GL_RGB32F; + m_FmtToGLFmtMap[ TEX_FORMAT_RGB32_UINT ] = GL_RGB32UI; + m_FmtToGLFmtMap[ TEX_FORMAT_RGB32_SINT ] = GL_RGB32I; + + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA16_TYPELESS ] = GL_RGBA16F; + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA16_FLOAT ] = GL_RGBA16F; + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA16_UNORM ] = GL_RGBA16; + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA16_UINT ] = GL_RGBA16UI; + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA16_SNORM ] = GL_RGBA16_SNORM; + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA16_SINT ] = GL_RGBA16I; + + m_FmtToGLFmtMap[ TEX_FORMAT_RG32_TYPELESS ] = GL_RG32F; + m_FmtToGLFmtMap[ TEX_FORMAT_RG32_FLOAT ] = GL_RG32F; + m_FmtToGLFmtMap[ TEX_FORMAT_RG32_UINT ] = GL_RG32UI; + m_FmtToGLFmtMap[ TEX_FORMAT_RG32_SINT ] = GL_RG32I; + + m_FmtToGLFmtMap[ TEX_FORMAT_R32G8X24_TYPELESS ] = GL_DEPTH32F_STENCIL8; + m_FmtToGLFmtMap[ TEX_FORMAT_D32_FLOAT_S8X24_UINT ] = GL_DEPTH32F_STENCIL8; + m_FmtToGLFmtMap[ TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS ]=GL_DEPTH32F_STENCIL8; + m_FmtToGLFmtMap[ TEX_FORMAT_X32_TYPELESS_G8X24_UINT ]= 0;//GL_DEPTH32F_STENCIL8; + + m_FmtToGLFmtMap[ TEX_FORMAT_RGB10A2_TYPELESS ] = GL_RGB10_A2; + m_FmtToGLFmtMap[ TEX_FORMAT_RGB10A2_UNORM ] = GL_RGB10_A2; + m_FmtToGLFmtMap[ TEX_FORMAT_RGB10A2_UINT ] = GL_RGB10_A2UI; + m_FmtToGLFmtMap[ TEX_FORMAT_R11G11B10_FLOAT ] = GL_R11F_G11F_B10F; + + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA8_TYPELESS ] = GL_RGBA8; + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA8_UNORM ] = GL_RGBA8; + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA8_UNORM_SRGB ] = GL_SRGB8_ALPHA8; + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA8_UINT ] = GL_RGBA8UI; + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA8_SNORM ] = GL_RGBA8_SNORM; + m_FmtToGLFmtMap[ TEX_FORMAT_RGBA8_SINT ] = GL_RGBA8I; + + m_FmtToGLFmtMap[ TEX_FORMAT_RG16_TYPELESS ] = GL_RG16F; + m_FmtToGLFmtMap[ TEX_FORMAT_RG16_FLOAT ] = GL_RG16F; + m_FmtToGLFmtMap[ TEX_FORMAT_RG16_UNORM ] = GL_RG16; + m_FmtToGLFmtMap[ TEX_FORMAT_RG16_UINT ] = GL_RG16UI; + m_FmtToGLFmtMap[ TEX_FORMAT_RG16_SNORM ] = GL_RG16_SNORM; + m_FmtToGLFmtMap[ TEX_FORMAT_RG16_SINT ] = GL_RG16I; + + m_FmtToGLFmtMap[ TEX_FORMAT_R32_TYPELESS ] = GL_R32F; + m_FmtToGLFmtMap[ TEX_FORMAT_D32_FLOAT ] = GL_DEPTH_COMPONENT32F; + m_FmtToGLFmtMap[ TEX_FORMAT_R32_FLOAT ] = GL_R32F; + m_FmtToGLFmtMap[ TEX_FORMAT_R32_UINT ] = GL_R32UI; + m_FmtToGLFmtMap[ TEX_FORMAT_R32_SINT ] = GL_R32I; + + m_FmtToGLFmtMap[ TEX_FORMAT_R24G8_TYPELESS ] = GL_DEPTH24_STENCIL8; + m_FmtToGLFmtMap[ TEX_FORMAT_D24_UNORM_S8_UINT ] = GL_DEPTH24_STENCIL8; + m_FmtToGLFmtMap[ TEX_FORMAT_R24_UNORM_X8_TYPELESS ] = GL_DEPTH24_STENCIL8; + m_FmtToGLFmtMap[ TEX_FORMAT_X24_TYPELESS_G8_UINT ] = 0;//GL_DEPTH24_STENCIL8; + + m_FmtToGLFmtMap[ TEX_FORMAT_RG8_TYPELESS ] = GL_RG8; + m_FmtToGLFmtMap[ TEX_FORMAT_RG8_UNORM ] = GL_RG8; + m_FmtToGLFmtMap[ TEX_FORMAT_RG8_UINT ] = GL_RG8UI; + m_FmtToGLFmtMap[ TEX_FORMAT_RG8_SNORM ] = GL_RG8_SNORM; + m_FmtToGLFmtMap[ TEX_FORMAT_RG8_SINT ] = GL_RG8I; + + m_FmtToGLFmtMap[ TEX_FORMAT_R16_TYPELESS ] = GL_R16F; + m_FmtToGLFmtMap[ TEX_FORMAT_R16_FLOAT ] = GL_R16F; + m_FmtToGLFmtMap[ TEX_FORMAT_D16_UNORM ] = GL_DEPTH_COMPONENT16; + m_FmtToGLFmtMap[ TEX_FORMAT_R16_UNORM ] = GL_R16; + m_FmtToGLFmtMap[ TEX_FORMAT_R16_UINT ] = GL_R16UI; + m_FmtToGLFmtMap[ TEX_FORMAT_R16_SNORM ] = GL_R16_SNORM; + m_FmtToGLFmtMap[ TEX_FORMAT_R16_SINT ] = GL_R16I; + + m_FmtToGLFmtMap[ TEX_FORMAT_R8_TYPELESS ] = GL_R8; + m_FmtToGLFmtMap[ TEX_FORMAT_R8_UNORM ] = GL_R8; + m_FmtToGLFmtMap[ TEX_FORMAT_R8_UINT ] = GL_R8UI; + m_FmtToGLFmtMap[ TEX_FORMAT_R8_SNORM ] = GL_R8_SNORM; + m_FmtToGLFmtMap[ TEX_FORMAT_R8_SINT ] = GL_R8I; + m_FmtToGLFmtMap[ TEX_FORMAT_A8_UNORM ] = 0; + + m_FmtToGLFmtMap[ TEX_FORMAT_R1_UNORM ] = 0; + + m_FmtToGLFmtMap[ TEX_FORMAT_RGB9E5_SHAREDEXP ] = GL_RGB9_E5; + m_FmtToGLFmtMap[ TEX_FORMAT_RG8_B8G8_UNORM ] = 0; + m_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; + m_FmtToGLFmtMap[ TEX_FORMAT_BC1_TYPELESS ] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + m_FmtToGLFmtMap[ TEX_FORMAT_BC1_UNORM ] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + m_FmtToGLFmtMap[ TEX_FORMAT_BC1_UNORM_SRGB ] = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; + m_FmtToGLFmtMap[ TEX_FORMAT_BC2_TYPELESS ] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + m_FmtToGLFmtMap[ TEX_FORMAT_BC2_UNORM ] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + m_FmtToGLFmtMap[ TEX_FORMAT_BC2_UNORM_SRGB ] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; + m_FmtToGLFmtMap[ TEX_FORMAT_BC3_TYPELESS ] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + m_FmtToGLFmtMap[ TEX_FORMAT_BC3_UNORM ] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + m_FmtToGLFmtMap[ TEX_FORMAT_BC3_UNORM_SRGB ] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + m_FmtToGLFmtMap[ TEX_FORMAT_BC4_TYPELESS ] = GL_COMPRESSED_RED_RGTC1; + m_FmtToGLFmtMap[ TEX_FORMAT_BC4_UNORM ] = GL_COMPRESSED_RED_RGTC1; + m_FmtToGLFmtMap[ TEX_FORMAT_BC4_SNORM ] = GL_COMPRESSED_SIGNED_RED_RGTC1; + m_FmtToGLFmtMap[ TEX_FORMAT_BC5_TYPELESS ] = GL_COMPRESSED_RG_RGTC2; + m_FmtToGLFmtMap[ TEX_FORMAT_BC5_UNORM ] = GL_COMPRESSED_RG_RGTC2; + m_FmtToGLFmtMap[ TEX_FORMAT_BC5_SNORM ] = GL_COMPRESSED_SIGNED_RG_RGTC2; + m_FmtToGLFmtMap[ TEX_FORMAT_B5G6R5_UNORM ] = 0; + m_FmtToGLFmtMap[ TEX_FORMAT_B5G5R5A1_UNORM ] = 0; + m_FmtToGLFmtMap[ TEX_FORMAT_BGRA8_UNORM ] = 0; + m_FmtToGLFmtMap[ TEX_FORMAT_BGRX8_UNORM ] = 0; + m_FmtToGLFmtMap[ TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM ] = 0; + m_FmtToGLFmtMap[ TEX_FORMAT_BGRA8_TYPELESS ] = 0; + m_FmtToGLFmtMap[ TEX_FORMAT_BGRA8_UNORM_SRGB ] = 0; + m_FmtToGLFmtMap[ TEX_FORMAT_BGRX8_TYPELESS ] = 0; + m_FmtToGLFmtMap[ TEX_FORMAT_BGRX8_UNORM_SRGB ] = 0; + m_FmtToGLFmtMap[ TEX_FORMAT_BC6H_TYPELESS ] = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; + m_FmtToGLFmtMap[ TEX_FORMAT_BC6H_UF16 ] = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; + m_FmtToGLFmtMap[ TEX_FORMAT_BC6H_SF16 ] = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; + m_FmtToGLFmtMap[ TEX_FORMAT_BC7_TYPELESS ] = GL_COMPRESSED_RGBA_BPTC_UNORM; + m_FmtToGLFmtMap[ TEX_FORMAT_BC7_UNORM ] = GL_COMPRESSED_RGBA_BPTC_UNORM; + m_FmtToGLFmtMap[ TEX_FORMAT_BC7_UNORM_SRGB ] = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; } + GLenum operator[](TEXTURE_FORMAT TexFormat)const + { + VERIFY_EXPR(TexFormat < _countof(m_FmtToGLFmtMap)); + return m_FmtToGLFmtMap[TexFormat]; + } + +private: + GLenum m_FmtToGLFmtMap[TEX_FORMAT_NUM_FORMATS] = {0}; +}; + +GLenum TexFormatToGLInternalTexFormat(TEXTURE_FORMAT TexFormat, Uint32 BindFlags) +{ + static const FormatToGLInternalTexFormatMap FormatMap; if( TexFormat >= TEX_FORMAT_UNKNOWN && TexFormat < TEX_FORMAT_NUM_FORMATS ) { - auto GLFormat = FmtToGLFmtMap[TexFormat]; + auto GLFormat = FormatMap[TexFormat]; if( BindFlags != 0 ) GLFormat = CorrectGLTexFormat( GLFormat, BindFlags ); return GLFormat; @@ -171,6 +181,61 @@ GLenum TexFormatToGLInternalTexFormat(TEXTURE_FORMAT TexFormat, Uint32 BindFlags } } +class InternalTexFormatToTexFormatMap +{ +public: + InternalTexFormatToTexFormatMap() + { + for (TEXTURE_FORMAT TexFmt = TEX_FORMAT_UNKNOWN; TexFmt < TEX_FORMAT_NUM_FORMATS; TexFmt = static_cast(static_cast(TexFmt) + 1) ) + { + auto ComponentType = GetTextureFormatAttribs(TexFmt).ComponentType; + if ( ComponentType == COMPONENT_TYPE_UNDEFINED || + ComponentType == COMPONENT_TYPE_DEPTH_STENCIL || + TexFmt == TEX_FORMAT_RGB10A2_TYPELESS || + TexFmt == TEX_FORMAT_BC1_TYPELESS || + TexFmt == TEX_FORMAT_BC2_TYPELESS || + TexFmt == TEX_FORMAT_BC3_TYPELESS || + TexFmt == TEX_FORMAT_BC4_TYPELESS || + TexFmt == TEX_FORMAT_BC5_TYPELESS || + TexFmt == TEX_FORMAT_BC6H_TYPELESS || + TexFmt == TEX_FORMAT_BC7_TYPELESS) + continue; // Skip typeless and depth-stencil formats + auto GlTexFormat = TexFormatToGLInternalTexFormat(TexFmt); + if (GlTexFormat != 0) + { + VERIFY_EXPR(m_FormatMap.find(GlTexFormat) == m_FormatMap.end()); + m_FormatMap[GlTexFormat] = TexFmt; + } + m_FormatMap[TexFormatToGLInternalTexFormat(TEX_FORMAT_D32_FLOAT_S8X24_UINT)] = TEX_FORMAT_D32_FLOAT_S8X24_UINT; + m_FormatMap[TexFormatToGLInternalTexFormat(TEX_FORMAT_D24_UNORM_S8_UINT)] = TEX_FORMAT_D24_UNORM_S8_UINT; + } + } + + TEXTURE_FORMAT operator[](GLenum GlFormat)const + { + auto formatIt = m_FormatMap.find(GlFormat); + if (formatIt != m_FormatMap.end()) + { + VERIFY_EXPR(GlFormat == TexFormatToGLInternalTexFormat(formatIt->second)); + return formatIt->second; + } + else + { + UNEXPECTED("Unknown GL format"); + return TEX_FORMAT_UNKNOWN; + } + } + +private: + std::unordered_map m_FormatMap; +}; + +TEXTURE_FORMAT GLInternalTexFormatToTexFormat(GLenum GlFormat) +{ + static const InternalTexFormatToTexFormatMap FormatMap; + return FormatMap[GlFormat]; +} + GLenum CorrectGLTexFormat( GLenum GLTexFormat, Uint32 BindFlags ) { if( BindFlags & BIND_DEPTH_STENCIL ) diff --git a/Graphics/GraphicsEngineOpenGL/src/GraphicsEngineOpenGL.def b/Graphics/GraphicsEngineOpenGL/src/GraphicsEngineOpenGL.def index 3a128b26..2d2ee59f 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GraphicsEngineOpenGL.def +++ b/Graphics/GraphicsEngineOpenGL/src/GraphicsEngineOpenGL.def @@ -1,2 +1,2 @@ EXPORTS - CreateDeviceAndSwapChainGL \ No newline at end of file + GetEngineFactoryOpenGL \ No newline at end of file diff --git a/Graphics/GraphicsEngineOpenGL/src/HLSL2GLSLConverter.cpp b/Graphics/GraphicsEngineOpenGL/src/HLSL2GLSLConverter.cpp deleted file mode 100644 index 4333f60d..00000000 --- a/Graphics/GraphicsEngineOpenGL/src/HLSL2GLSLConverter.cpp +++ /dev/null @@ -1,3261 +0,0 @@ -/* Copyright 2015-2017 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 -#include - -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 -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 -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 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 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 -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 -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 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 pIncludeDataStream; - m_pSourceStreamFactory->CreateInputStream( IncludeName.c_str(), &pIncludeDataStream ); - if( !pIncludeDataStream ) - LOG_ERROR_AND_THROW( "Failed to open include file ", IncludeName ) - RefCntAutoPtr pIncludeData( new Diligent::DataBlobImpl ); - pIncludeDataStream->Read( pIncludeData ); - - // Get include text - auto IncludeText = reinterpret_cast (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 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 -> sampler2D -// - Texture3D -> usampler3D -// - Texture2DArray -> isampler2DArray -// - Texture2D -> sampler2D -// - To distinguish if sampler should be shadow or not, the function tries to find _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 &Samplers, - ObjectsTypeHashType &Objects ) -{ - auto TexDeclToken = Token; - auto TextureDim = TexDeclToken->Type; - // Texture2D < float > ... ; - // ^ - bool IsRWTexture = - TextureDim == TokenType::RWTexture1D || - TextureDim == TokenType::RWTexture1DArray || - TextureDim == TokenType::RWTexture2D || - TextureDim == TokenType::RWTexture2DArray || - TextureDim == 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( (TextureDim == TokenType::Texture2DMS || - TextureDim == 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 - // ^ - ParseImageFormat( Token->Delimiter, ImgFormat ); - if( ImgFormat.length() == 0 ) - { - // RWTexture2D - // ^ - // 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( TextureDim ) - { - 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 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 - // Texture2DName; - // 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(TextureDim, "", "\n") ); - // Texture2D TexName; - // 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 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& 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& 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& 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& 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 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 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 - // 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/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 8ef0bedd..ad0a2215 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -31,10 +31,9 @@ namespace Diligent { -PipelineStateGLImpl::PipelineStateGLImpl(FixedBlockMemoryAllocator &PSOAllocator, class RenderDeviceGLImpl *pDeviceGL, const PipelineStateDesc& PipelineDesc, bool bIsDeviceInternal) : - TPipelineStateBase(PSOAllocator, pDeviceGL, PipelineDesc, bIsDeviceInternal), - m_GLProgram(false), - m_GLProgPipeline(false) +PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters *pRefCounters, class RenderDeviceGLImpl *pDeviceGL, const PipelineStateDesc& PipelineDesc, bool bIsDeviceInternal) : + TPipelineStateBase(pRefCounters, pDeviceGL, PipelineDesc, bIsDeviceInternal), + m_GLProgram(false) { auto &DeviceCaps = pDeviceGL->GetDeviceCaps(); @@ -48,18 +47,8 @@ void PipelineStateGLImpl::LinkGLProgram(bool bIsProgramPipelineSupported) { if( bIsProgramPipelineSupported ) { - // Create new progam pipeline - m_GLProgPipeline.Create(); - for( Uint32 Shader = 0; Shader < m_NumShaders; ++Shader ) - { - auto *pCurrShader = static_cast(m_ppShaders[Shader]); - 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( m_GLProgPipeline, GLShaderBit, pCurrShader->m_GlProgObj ); - CHECK_GL_ERROR( "glUseProgramStages() failed" ); - } + // Program pipelines are not shared between GL contexts, so we cannot create + // it now } else { @@ -137,7 +126,7 @@ void PipelineStateGLImpl::LinkGLProgram(bool bIsProgramPipelineSupported) PipelineStateGLImpl::~PipelineStateGLImpl() { - static_cast( GetDevice() )->m_VAOCache.OnDestroyPSO(this); + static_cast( GetDevice() )->OnDestroyPSO(this); } IMPLEMENT_QUERY_INTERFACE( PipelineStateGLImpl, IID_PipelineStateGL, TPipelineStateBase ) @@ -162,8 +151,33 @@ void PipelineStateGLImpl::CreateShaderResourceBinding(IShaderResourceBinding **p { auto *pRenderDeviceGL = ValidatedCast( GetDevice() ); auto &SRBAllocator = pRenderDeviceGL->GetSRBAllocator(); - auto pResBinding = NEW( SRBAllocator, "ShaderResourceBindingGLImpl instance", ShaderResourceBindingGLImpl, this); + auto pResBinding = NEW_RC_OBJ( SRBAllocator, "ShaderResourceBindingGLImpl instance", ShaderResourceBindingGLImpl)(this); pResBinding->QueryInterface(IID_ShaderResourceBinding, reinterpret_cast(ppShaderResourceBinding)); } +GLObjectWrappers::GLPipelineObj &PipelineStateGLImpl::GetGLProgramPipeline(GLContext::NativeGLContextType Context) +{ + ThreadingTools::LockHelper Lock(m_ProgPipelineLockFlag); + auto it = m_GLProgPipelines.find(Context); + if (it != m_GLProgPipelines.end()) + return it->second; + else + { + // Create new progam pipeline + it = m_GLProgPipelines.emplace( Context, true ).first; + GLuint Pipeline = it->second; + for (Uint32 Shader = 0; Shader < m_NumShaders; ++Shader) + { + auto *pCurrShader = static_cast(m_ppShaders[Shader]); + 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(Pipeline, GLShaderBit, pCurrShader->m_GlProgObj); + CHECK_GL_ERROR("glUseProgramStages() failed"); + } + return it->second; + } +} + } diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceFactoryOpenGL.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceFactoryOpenGL.cpp index 04eb5e59..a18ca767 100644 --- a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceFactoryOpenGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceFactoryOpenGL.cpp @@ -30,6 +30,7 @@ #include "DeviceContextGLImpl.h" #include "SwapChainGLImpl.h" #include "EngineMemory.h" +#include "HLSL2GLSLConverterObject.h" #ifdef PLATFORM_ANDROID #include "RenderDeviceGLESImpl.h" @@ -44,6 +45,31 @@ namespace Diligent typedef RenderDeviceGLESImpl TRenderDeviceGLImpl; #endif +/// Engine factory for OpenGL implementation +class EngineFactoryOpenGLImpl : public IEngineFactoryOpenGL +{ +public: + static EngineFactoryOpenGLImpl* GetInstance() + { + static EngineFactoryOpenGLImpl TheFactory; + return &TheFactory; + } + + virtual void CreateDeviceAndSwapChainGL( const EngineCreationAttribs& CreationAttribs, + IRenderDevice **ppDevice, + IDeviceContext **ppImmediateContext, + const SwapChainDesc& SCDesc, + void *pNativeWndHandle, + ISwapChain **ppSwapChain )override final; + + virtual void CreateHLSL2GLSLConverter(IHLSL2GLSLConverter **ppConverter)override final; + + virtual void AttachToActiveGLContext( const EngineCreationAttribs& CreationAttribs, + IRenderDevice **ppDevice, + IDeviceContext **ppImmediateContext )override final; +}; + + /// Creates render device, device context and swap chain for OpenGL/GLES-based engine implementation @@ -59,40 +85,39 @@ namespace Diligent /// * On Android platform, this should be a pointer to the native window (ANativeWindow*) /// \param [out] ppSwapChain - Address of the memory location where pointer to the new /// swap chain will be written. -void CreateDeviceAndSwapChainGL( const EngineCreationAttribs& CreationAttribs, - IRenderDevice **ppDevice, - IDeviceContext **ppImmediateContext, - const SwapChainDesc& SCDesc, - void *pNativeWndHandle, - Diligent::ISwapChain **ppSwapChain ) +void EngineFactoryOpenGLImpl::CreateDeviceAndSwapChainGL( const EngineCreationAttribs& CreationAttribs, + IRenderDevice **ppDevice, + IDeviceContext **ppImmediateContext, + const SwapChainDesc& SCDesc, + void *pNativeWndHandle, + Diligent::ISwapChain **ppSwapChain ) { - VERIFY( ppDevice && ppImmediateContext && ppSwapChain, "Null pointer is provided" ); + VERIFY( ppDevice && ppImmediateContext && ppSwapChain, "Null pointer provided" ); if( !ppDevice || !ppImmediateContext || !ppSwapChain ) return; - SetRawAllocator(CreationAttribs.pRawMemAllocator); - *ppDevice = nullptr; *ppImmediateContext = nullptr; *ppSwapChain = nullptr; try { + SetRawAllocator(CreationAttribs.pRawMemAllocator); auto &RawMemAllocator = GetRawAllocator(); ContextInitInfo InitInfo; InitInfo.pNativeWndHandle = pNativeWndHandle; InitInfo.SwapChainAttribs = SCDesc; - RenderDeviceGLImpl *pRenderDeviceOpenGL( NEW(RawMemAllocator, "TRenderDeviceGLImpl instance", TRenderDeviceGLImpl, InitInfo ) ); + RenderDeviceGLImpl *pRenderDeviceOpenGL( NEW_RC_OBJ(RawMemAllocator, "TRenderDeviceGLImpl instance", TRenderDeviceGLImpl)(RawMemAllocator, InitInfo) ); pRenderDeviceOpenGL->QueryInterface(IID_RenderDevice, reinterpret_cast(ppDevice) ); - DeviceContextGLImpl *pDeviceContextOpenGL( NEW(RawMemAllocator, "DeviceContextGLImpl instance", DeviceContextGLImpl, pRenderDeviceOpenGL, false ) ); + DeviceContextGLImpl *pDeviceContextOpenGL( NEW_RC_OBJ(RawMemAllocator, "DeviceContextGLImpl instance", DeviceContextGLImpl)(pRenderDeviceOpenGL, false ) ); // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceOpenGL will // keep a weak reference to the context pDeviceContextOpenGL->QueryInterface(IID_DeviceContext, reinterpret_cast(ppImmediateContext) ); pRenderDeviceOpenGL->SetImmediateContext(pDeviceContextOpenGL); - SwapChainGLImpl *pSwapChainGL = NEW(RawMemAllocator, "SwapChainGLImpl instance", SwapChainGLImpl, SCDesc, pRenderDeviceOpenGL, pDeviceContextOpenGL ); + SwapChainGLImpl *pSwapChainGL = NEW_RC_OBJ(RawMemAllocator, "SwapChainGLImpl instance", SwapChainGLImpl)(SCDesc, pRenderDeviceOpenGL, pDeviceContextOpenGL ); pSwapChainGL->QueryInterface(IID_SwapChain, reinterpret_cast(ppSwapChain) ); pDeviceContextOpenGL->SetSwapChain(pSwapChainGL); @@ -124,10 +149,66 @@ void CreateDeviceAndSwapChainGL( const EngineCreationAttribs& CreationAttribs, } } + +/// Creates render device, device context and attaches to existing GL context + +/// \param [in] CreationAttribs - Engine creation attributes. +/// \param [out] ppDevice - Address of the memory location where pointer to +/// the created device will be written. +/// \param [out] ppImmediateContext - Address of the memory location where pointers to +/// the immediate context will be written. +void EngineFactoryOpenGLImpl::AttachToActiveGLContext( const EngineCreationAttribs& CreationAttribs, + IRenderDevice **ppDevice, + IDeviceContext **ppImmediateContext ) +{ + VERIFY( ppDevice && ppImmediateContext, "Null pointer provided" ); + if( !ppDevice || !ppImmediateContext ) + return; + + *ppDevice = nullptr; + *ppImmediateContext = nullptr; + + try + { + SetRawAllocator(CreationAttribs.pRawMemAllocator); + auto &RawMemAllocator = GetRawAllocator(); + + ContextInitInfo InitInfo; + InitInfo.SwapChainAttribs.BufferCount = 0; + InitInfo.SwapChainAttribs.ColorBufferFormat = TEX_FORMAT_UNKNOWN; + InitInfo.SwapChainAttribs.DepthBufferFormat = TEX_FORMAT_UNKNOWN; + RenderDeviceGLImpl *pRenderDeviceOpenGL( NEW_RC_OBJ(RawMemAllocator, "TRenderDeviceGLImpl instance", TRenderDeviceGLImpl)(RawMemAllocator, InitInfo) ); + pRenderDeviceOpenGL->QueryInterface(IID_RenderDevice, reinterpret_cast(ppDevice) ); + + DeviceContextGLImpl *pDeviceContextOpenGL( NEW_RC_OBJ(RawMemAllocator, "DeviceContextGLImpl instance", DeviceContextGLImpl)(pRenderDeviceOpenGL, false ) ); + // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceOpenGL will + // keep a weak reference to the context + pDeviceContextOpenGL->QueryInterface(IID_DeviceContext, reinterpret_cast(ppImmediateContext) ); + pRenderDeviceOpenGL->SetImmediateContext(pDeviceContextOpenGL); + } + catch( const std::runtime_error & ) + { + if( *ppDevice ) + { + (*ppDevice)->Release(); + *ppDevice = nullptr; + } + + if( *ppImmediateContext ) + { + (*ppImmediateContext)->Release(); + *ppImmediateContext = nullptr; + } + + LOG_ERROR( "Failed to initialize OpenGL-based render device" ); + } +} + #ifdef DOXYGEN /// Loads OpenGL-based engine implementation and exports factory functions -/// \param [out] CreateDeviceFunc - Pointer to the function that creates render device, device context and swap chain. -/// See CreateDeviceAndSwapChainGL(). +/// \param [out] GetFactoryFunc - Pointer to the function that returns pointer to the factory for +/// the OpenGL engine implementation +/// See EngineFactoryOpenGLImpl::CreateDeviceAndSwapChainGL(). /// \remarks Depending on the configuration and platform, the function loads different dll: /// Platform\\Configuration | Debug | Release /// --------------------------|------------------------------|---------------------------- @@ -135,26 +216,27 @@ void CreateDeviceAndSwapChainGL( const EngineCreationAttribs& CreationAttribs, /// Win32/x64 | GraphicsEngineOpenGL_64d.dll | GraphicsEngineOpenGL_64r.dll /// /// To load the library on Android, it is necessary to call System.loadLibrary("GraphicsEngineOpenGL") from Java. -void LoadGraphicsEngineOpenGL(CreateDeviceAndSwapChainGLType &CreateDeviceFunc) +void LoadGraphicsEngineOpenGL(GetEngineFactoryOpenGLType &GetFactoryFunc) { // This function is only required because DoxyGen refuses to generate documentation for a static function when SHOW_FILES==NO #error This function must never be compiled; } #endif +void EngineFactoryOpenGLImpl::CreateHLSL2GLSLConverter(IHLSL2GLSLConverter **ppConverter) +{ + HLSL2GLSLConverterObject *pConverter( NEW_RC_OBJ(GetRawAllocator(), "HLSL2GLSLConverterObject instance", HLSL2GLSLConverterObject)() ); + pConverter->QueryInterface( IID_HLSL2GLSLConverter, reinterpret_cast(ppConverter) ); +} + } extern "C" { API_QUALIFIER -void CreateDeviceAndSwapChainGL( const EngineCreationAttribs& CreationAttribs, - IRenderDevice **ppDevice, - IDeviceContext **ppImmediateContext, - const SwapChainDesc& SwapChainDesc, - void *pNativeWndHandle, - Diligent::ISwapChain **ppSwapChain ) +Diligent::IEngineFactoryOpenGL* GetEngineFactoryOpenGL() { - Diligent::CreateDeviceAndSwapChainGL( CreationAttribs, ppDevice, ppImmediateContext, SwapChainDesc, pNativeWndHandle, ppSwapChain ); + return Diligent::EngineFactoryOpenGLImpl::GetInstance(); } } diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLESImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLESImpl.cpp index 2897d97d..1aaa8ab2 100644 --- a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLESImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLESImpl.cpp @@ -27,8 +27,8 @@ namespace Diligent { - RenderDeviceGLESImpl::RenderDeviceGLESImpl( IMemoryAllocator &RawMemAllocator, const ContextInitInfo &InitInfo ) : - RenderDeviceGLImpl( RawMemAllocator, InitInfo ) + RenderDeviceGLESImpl::RenderDeviceGLESImpl( IReferenceCounters *pRefCounters, IMemoryAllocator &RawMemAllocator, const ContextInitInfo &InitInfo ) : + RenderDeviceGLImpl( pRefCounters, RawMemAllocator, InitInfo ) { } diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp index 5899b647..40d2074a 100644 --- a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp @@ -45,11 +45,10 @@ namespace Diligent { -RenderDeviceGLImpl :: RenderDeviceGLImpl(IMemoryAllocator &RawMemAllocator, const ContextInitInfo &InitInfo): - TRenderDeviceBase(RawMemAllocator, 0, sizeof(TextureBaseGL), sizeof(TextureViewGLImpl), sizeof(BufferGLImpl), sizeof(BufferViewGLImpl), sizeof(ShaderGLImpl), sizeof(SamplerGLImpl), sizeof(PipelineStateGLImpl), sizeof(ShaderResourceBindingGLImpl)), +RenderDeviceGLImpl :: RenderDeviceGLImpl(IReferenceCounters *pRefCounters, IMemoryAllocator &RawMemAllocator, const ContextInitInfo &InitInfo): + TRenderDeviceBase(pRefCounters, RawMemAllocator, 0, sizeof(TextureBaseGL), sizeof(TextureViewGLImpl), sizeof(BufferGLImpl), sizeof(BufferViewGLImpl), sizeof(ShaderGLImpl), sizeof(SamplerGLImpl), sizeof(PipelineStateGLImpl), sizeof(ShaderResourceBindingGLImpl)), // Device caps must be filled in before the constructor of Pipeline Cache is called! m_GLContext(InitInfo, m_DeviceCaps), - m_EmptyVAO(true), m_TexRegionRender(this) { GLint NumExtensions = 0; @@ -69,12 +68,12 @@ RenderDeviceGLImpl :: RenderDeviceGLImpl(IMemoryAllocator &RawMemAllocator, cons std::basic_string 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 ) + if( Vendor.find( "intel" ) != std::string::npos ) m_GPUInfo.Vendor = GPU_VENDOR::INTEL; - else if( Vendor.find( "nvidia" ) != string::npos ) + else if( Vendor.find( "nvidia" ) != std::string::npos ) m_GPUInfo.Vendor = GPU_VENDOR::NVIDIA; - else if( Vendor.find( "ati" ) != string::npos || - Vendor.find( "amd" ) != string::npos ) + else if( Vendor.find( "ati" ) != std::string::npos || + Vendor.find( "amd" ) != std::string::npos ) m_GPUInfo.Vendor = GPU_VENDOR::ATI; } @@ -82,14 +81,15 @@ RenderDeviceGLImpl :: ~RenderDeviceGLImpl() { } -IMPLEMENT_QUERY_INTERFACE( RenderDeviceGLImpl, IID_GLDeviceBaseInterface, TRenderDeviceBase ) +IMPLEMENT_QUERY_INTERFACE( RenderDeviceGLImpl, IID_RenderDeviceGL, TRenderDeviceBase ) void RenderDeviceGLImpl :: CreateBuffer(const BufferDesc& BuffDesc, const BufferData &BuffData, IBuffer **ppBuffer, bool bIsDeviceInternal) { CreateDeviceObject( "buffer", BuffDesc, ppBuffer, [&]() { - BufferGLImpl *pBufferOGL( NEW(m_BufObjAllocator, "BufferGLImpl instance", BufferGLImpl, m_BuffViewObjAllocator, this, BuffDesc, BuffData, bIsDeviceInternal ) ); + BufferGLImpl *pBufferOGL( NEW_RC_OBJ(m_BufObjAllocator, "BufferGLImpl instance", BufferGLImpl) + (m_BuffViewObjAllocator, this, BuffDesc, BuffData, bIsDeviceInternal ) ); pBufferOGL->QueryInterface( IID_Buffer, reinterpret_cast(ppBuffer) ); pBufferOGL->CreateDefaultViews(); OnCreateDeviceObject( pBufferOGL ); @@ -102,13 +102,27 @@ void RenderDeviceGLImpl :: CreateBuffer(const BufferDesc& BuffDesc, const Buffer CreateBuffer(BuffDesc, BuffData, ppBuffer, false); } +void RenderDeviceGLImpl :: CreateBufferFromGLHandle(Uint32 GLHandle, const BufferDesc &BuffDesc, IBuffer **ppBuffer) +{ + CreateDeviceObject( "buffer", BuffDesc, ppBuffer, + [&]() + { + BufferGLImpl *pBufferOGL( NEW_RC_OBJ(m_BufObjAllocator, "BufferGLImpl instance", BufferGLImpl) + (m_BuffViewObjAllocator, this, BuffDesc, GLHandle, false ) ); + pBufferOGL->QueryInterface( IID_Buffer, reinterpret_cast(ppBuffer) ); + pBufferOGL->CreateDefaultViews(); + OnCreateDeviceObject( pBufferOGL ); + } + ); +} void RenderDeviceGLImpl :: CreateShader(const ShaderCreationAttribs &ShaderCreationAttribs, IShader **ppShader, bool bIsDeviceInternal) { CreateDeviceObject( "shader", ShaderCreationAttribs.Desc, ppShader, [&]() { - ShaderGLImpl *pShaderOGL(NEW(m_ShaderObjAllocator, "ShaderGLImpl instance", ShaderGLImpl, this, ShaderCreationAttribs, bIsDeviceInternal)); + ShaderGLImpl *pShaderOGL(NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderGLImpl instance", ShaderGLImpl) + (this, ShaderCreationAttribs, bIsDeviceInternal)); pShaderOGL->QueryInterface(IID_Shader, reinterpret_cast(ppShader) ); OnCreateDeviceObject( pShaderOGL ); @@ -139,31 +153,38 @@ void RenderDeviceGLImpl :: CreateTexture(const TextureDesc& TexDesc, const Textu switch(TexDesc.Type) { case RESOURCE_DIM_TEX_1D: - pTextureOGL = NEW(m_TexObjAllocator, "Texture1D_OGL instance", Texture1D_OGL, m_TexViewObjAllocator, this, pDeviceContext, TexDesc, Data, bIsDeviceInternal); + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "Texture1D_OGL instance", Texture1D_OGL) + (m_TexViewObjAllocator, this, pDeviceContext, TexDesc, Data, bIsDeviceInternal); break; case RESOURCE_DIM_TEX_1D_ARRAY: - pTextureOGL = NEW(m_TexObjAllocator, "Texture1DArray_OGL instance", Texture1DArray_OGL, m_TexViewObjAllocator, this, pDeviceContext, TexDesc, Data, bIsDeviceInternal); + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "Texture1DArray_OGL instance", Texture1DArray_OGL) + (m_TexViewObjAllocator, this, pDeviceContext, TexDesc, Data, bIsDeviceInternal); break; case RESOURCE_DIM_TEX_2D: - pTextureOGL = NEW(m_TexObjAllocator, "Texture2D_OGL instance", Texture2D_OGL, m_TexViewObjAllocator, this, pDeviceContext, TexDesc, Data, bIsDeviceInternal); + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "Texture2D_OGL instance", Texture2D_OGL) + (m_TexViewObjAllocator, this, pDeviceContext, TexDesc, Data, bIsDeviceInternal); break; case RESOURCE_DIM_TEX_2D_ARRAY: - pTextureOGL = NEW(m_TexObjAllocator, "Texture2DArray_OGL instance", Texture2DArray_OGL, m_TexViewObjAllocator, this, pDeviceContext, TexDesc, Data, bIsDeviceInternal); + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "Texture2DArray_OGL instance", Texture2DArray_OGL) + (m_TexViewObjAllocator, this, pDeviceContext, TexDesc, Data, bIsDeviceInternal); break; case RESOURCE_DIM_TEX_3D: - pTextureOGL = NEW(m_TexObjAllocator, "Texture3D_OGL instance", Texture3D_OGL, m_TexViewObjAllocator, this, pDeviceContext, TexDesc, Data, bIsDeviceInternal); + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "Texture3D_OGL instance", Texture3D_OGL) + (m_TexViewObjAllocator, this, pDeviceContext, TexDesc, Data, bIsDeviceInternal); break; case RESOURCE_DIM_TEX_CUBE: - pTextureOGL = NEW(m_TexObjAllocator, "TextureCube_OGL instance", TextureCube_OGL, m_TexViewObjAllocator, this, pDeviceContext, TexDesc, Data, bIsDeviceInternal); + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "TextureCube_OGL instance", TextureCube_OGL) + (m_TexViewObjAllocator, this, pDeviceContext, TexDesc, Data, bIsDeviceInternal); break; case RESOURCE_DIM_TEX_CUBE_ARRAY: - pTextureOGL = NEW(m_TexObjAllocator, "TextureCubeArray_OGL instance", TextureCubeArray_OGL, m_TexViewObjAllocator, this, pDeviceContext, TexDesc, Data, bIsDeviceInternal); + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "TextureCubeArray_OGL instance", TextureCubeArray_OGL) + (m_TexViewObjAllocator, 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?)" ); @@ -181,6 +202,62 @@ void RenderDeviceGLImpl::CreateTexture(const TextureDesc& TexDesc, const Texture CreateTexture(TexDesc, Data, ppTexture, false); } +void RenderDeviceGLImpl::CreateTextureFromGLHandle(Uint32 GLHandle, const TextureDesc &TexDesc, ITexture **ppTexture) +{ + CreateDeviceObject( "texture", TexDesc, ppTexture, + [&]() + { + auto spDeviceContext = GetImmediateContext(); + VERIFY(spDeviceContext, "Immediate device context has been destroyed"); + auto pDeviceContext = ValidatedCast( spDeviceContext.RawPtr() ); + TextureBaseGL *pTextureOGL = nullptr; + switch(TexDesc.Type) + { + case RESOURCE_DIM_TEX_1D: + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "Texture1D_OGL instance", Texture1D_OGL) + (m_TexViewObjAllocator, this, pDeviceContext, TexDesc, GLHandle); + break; + + case RESOURCE_DIM_TEX_1D_ARRAY: + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "Texture1DArray_OGL instance", Texture1DArray_OGL) + (m_TexViewObjAllocator, this, pDeviceContext, TexDesc, GLHandle); + break; + + case RESOURCE_DIM_TEX_2D: + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "Texture2D_OGL instance", Texture2D_OGL) + (m_TexViewObjAllocator, this, pDeviceContext, TexDesc, GLHandle); + break; + + case RESOURCE_DIM_TEX_2D_ARRAY: + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "Texture2DArray_OGL instance", Texture2DArray_OGL) + (m_TexViewObjAllocator, this, pDeviceContext, TexDesc, GLHandle); + break; + + case RESOURCE_DIM_TEX_3D: + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "Texture3D_OGL instance", Texture3D_OGL) + (m_TexViewObjAllocator, this, pDeviceContext, TexDesc, GLHandle); + break; + + case RESOURCE_DIM_TEX_CUBE: + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "TextureCube_OGL instance", TextureCube_OGL) + (m_TexViewObjAllocator, this, pDeviceContext, TexDesc, GLHandle); + break; + + case RESOURCE_DIM_TEX_CUBE_ARRAY: + pTextureOGL = NEW_RC_OBJ(m_TexObjAllocator, "TextureCubeArray_OGL instance", TextureCubeArray_OGL) + (m_TexViewObjAllocator, this, pDeviceContext, TexDesc, GLHandle); + 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(ppTexture) ); + pTextureOGL->CreateDefaultViews(); + OnCreateDeviceObject( pTextureOGL ); + } + ); +} + void RenderDeviceGLImpl :: CreateSampler(const SamplerDesc& SamplerDesc, ISampler **ppSampler, bool bIsDeviceInternal) { CreateDeviceObject( "sampler", SamplerDesc, ppSampler, @@ -189,7 +266,8 @@ void RenderDeviceGLImpl :: CreateSampler(const SamplerDesc& SamplerDesc, ISample m_SamplersRegistry.Find( SamplerDesc, reinterpret_cast(ppSampler) ); if( *ppSampler == nullptr ) { - SamplerGLImpl *pSamplerOGL( NEW(m_SamplerObjAllocator, "SamplerGLImpl instance", SamplerGLImpl, this, SamplerDesc, bIsDeviceInternal ) ); + SamplerGLImpl *pSamplerOGL( NEW_RC_OBJ(m_SamplerObjAllocator, "SamplerGLImpl instance", SamplerGLImpl) + (this, SamplerDesc, bIsDeviceInternal ) ); pSamplerOGL->QueryInterface( IID_Sampler, reinterpret_cast(ppSampler) ); OnCreateDeviceObject( pSamplerOGL ); m_SamplersRegistry.Add( SamplerDesc, *ppSampler ); @@ -214,7 +292,8 @@ void RenderDeviceGLImpl::CreatePipelineState(const PipelineStateDesc &PipelineDe CreateDeviceObject( "Pipeline state", PipelineDesc, ppPipelineState, [&]() { - PipelineStateGLImpl *pPipelineStateOGL( NEW(m_PSOAllocator, "PipelineStateGLImpl instance", PipelineStateGLImpl, this, PipelineDesc, bIsDeviceInternal ) ); + PipelineStateGLImpl *pPipelineStateOGL( NEW_RC_OBJ(m_PSOAllocator, "PipelineStateGLImpl instance", PipelineStateGLImpl) + (this, PipelineDesc, bIsDeviceInternal ) ); pPipelineStateOGL->QueryInterface( IID_PipelineState, reinterpret_cast(ppPipelineState) ); OnCreateDeviceObject( pPipelineStateOGL ); } @@ -231,7 +310,7 @@ void RenderDeviceGLImpl::FlagSupportedTexFormats() { const auto &DeviceCaps = GetDeviceCaps(); bool bGL33OrAbove = DeviceCaps.DevType == DeviceType::OpenGL && - (DeviceCaps.MajorVersion >= 4 || DeviceCaps.MajorVersion == 3 && DeviceCaps.MinorVersion >= 3); + (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" ); @@ -350,7 +429,7 @@ void RenderDeviceGLImpl::FlagSupportedTexFormats() #ifdef _DEBUG bool bGL43OrAbove = DeviceCaps.DevType == DeviceType::OpenGL && - (DeviceCaps.MajorVersion >= 5 || DeviceCaps.MajorVersion == 4 && DeviceCaps.MinorVersion >= 3); + (DeviceCaps.MajorVersion >= 5 || (DeviceCaps.MajorVersion == 4 && DeviceCaps.MinorVersion >= 3) ); const int TestTextureDim = 32; const int MaxTexelSize = 16; @@ -392,7 +471,7 @@ void RenderDeviceGLImpl::FlagSupportedTexFormats() // 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 ); + const auto &TransferAttribs = GetNativePixelTransferAttribs( FmtInfo->Format ); if( FmtInfo->ComponentType != COMPONENT_TYPE_COMPRESSED ) { glTexSubImage2D( GL_TEXTURE_2D, 0, // mip level @@ -574,4 +653,38 @@ void RenderDeviceGLImpl :: QueryDeviceCaps() } } + +FBOCache& RenderDeviceGLImpl::GetFBOCache(GLContext::NativeGLContextType Context) +{ + ThreadingTools::LockHelper FBOCacheLock(m_FBOCacheLockFlag); + return m_FBOCache[Context]; +} + +void RenderDeviceGLImpl::OnReleaseTexture(ITexture *pTexture) +{ + ThreadingTools::LockHelper FBOCacheLock(m_FBOCacheLockFlag); + for (auto& FBOCacheIt : m_FBOCache) + FBOCacheIt.second.OnReleaseTexture(pTexture); +} + +VAOCache& RenderDeviceGLImpl::GetVAOCache(GLContext::NativeGLContextType Context) +{ + ThreadingTools::LockHelper VAOCacheLock(m_VAOCacheLockFlag); + return m_VAOCache[Context]; +} + +void RenderDeviceGLImpl::OnDestroyPSO(IPipelineState *pPSO) +{ + ThreadingTools::LockHelper VAOCacheLock(m_VAOCacheLockFlag); + for (auto& VAOCacheIt : m_VAOCache) + VAOCacheIt.second.OnDestroyPSO(pPSO); +} + +void RenderDeviceGLImpl::OnDestroyBuffer(IBuffer *pBuffer) +{ + ThreadingTools::LockHelper VAOCacheLock(m_VAOCacheLockFlag); + for (auto& VAOCacheIt : m_VAOCache) + VAOCacheIt.second.OnDestroyBuffer(pBuffer); +} + } diff --git a/Graphics/GraphicsEngineOpenGL/src/SamplerGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/SamplerGLImpl.cpp index 5d236421..143aa469 100644 --- a/Graphics/GraphicsEngineOpenGL/src/SamplerGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/SamplerGLImpl.cpp @@ -29,8 +29,8 @@ namespace Diligent { -SamplerGLImpl::SamplerGLImpl(FixedBlockMemoryAllocator &SamplerObjAllocator, class RenderDeviceGLImpl *pDeviceGL, const SamplerDesc& SamplerDesc, bool bIsDeviceInternal) : - TSamplerBase( SamplerObjAllocator, pDeviceGL, SamplerDesc, bIsDeviceInternal ), +SamplerGLImpl::SamplerGLImpl(IReferenceCounters *pRefCounters, class RenderDeviceGLImpl *pDeviceGL, const SamplerDesc& SamplerDesc, bool bIsDeviceInternal) : + TSamplerBase( pRefCounters, pDeviceGL, SamplerDesc, bIsDeviceInternal ), m_GlSampler(true) { const auto& SamCaps = pDeviceGL->GetDeviceCaps().SamCaps; diff --git a/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp index c51ee3bf..2ef716ed 100644 --- a/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp @@ -26,20 +26,15 @@ #include "ShaderGLImpl.h" #include "RenderDeviceGLImpl.h" #include "DataBlobImpl.h" -#include "HLSL2GLSLConverter.h" +#include "HLSL2GLSLConverterImpl.h" using namespace Diligent; namespace Diligent { -static const Char* g_GLSLDefinitions = -{ - #include "GLSLDefinitions_inc.h" -}; - -ShaderGLImpl::ShaderGLImpl(FixedBlockMemoryAllocator& ShaderObjAllocator, RenderDeviceGLImpl *pDeviceGL, const ShaderCreationAttribs &ShaderCreationAttribs, bool bIsDeviceInternal) : - TShaderBase( ShaderObjAllocator, pDeviceGL, ShaderCreationAttribs.Desc, bIsDeviceInternal ), +ShaderGLImpl::ShaderGLImpl(IReferenceCounters *pRefCounters, RenderDeviceGLImpl *pDeviceGL, const ShaderCreationAttribs &ShaderCreationAttribs, bool bIsDeviceInternal) : + TShaderBase( pRefCounters, pDeviceGL, ShaderCreationAttribs.Desc, bIsDeviceInternal ), m_GlProgObj(false), m_GLShaderObj( false, GLObjectWrappers::GLShaderObjCreateReleaseHelper( GetGLShaderType( m_Desc.ShaderType ) ) ) { @@ -50,15 +45,25 @@ ShaderGLImpl::ShaderGLImpl(FixedBlockMemoryAllocator& ShaderObjAllocator, Render // Not specifying lengths causes shader compilation errors on Android std::vector Lenghts; - ShaderStrings.push_back( + String Settings; + #if defined(PLATFORM_WIN32) + Settings.append( "#version 430 core\n" "#define DESKTOP_GL 1\n" + ); #elif defined(ANDROID) + Settings.append( "#version 310 es\n" - - "#extension GL_EXT_shader_io_blocks : enable\n" // This is required on NVidia + ); + if(m_Desc.ShaderType == SHADER_TYPE_GEOMETRY) + Settings.append("#extension GL_EXT_geometry_shader : enable\n"); + + if(m_Desc.ShaderType == SHADER_TYPE_HULL || m_Desc.ShaderType == SHADER_TYPE_DOMAIN) + Settings.append("#extension GL_EXT_tessellation_shader : enable\n"); + + Settings.append( "#ifndef GL_ES\n" "# define GL_ES 1\n" "#endif\n" @@ -106,6 +111,7 @@ ShaderGLImpl::ShaderGLImpl(FixedBlockMemoryAllocator& ShaderObjAllocator, Render "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 @@ -113,9 +119,12 @@ ShaderGLImpl::ShaderGLImpl(FixedBlockMemoryAllocator& ShaderObjAllocator, Render // 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. + Settings.append( "layout(std140) uniform;\n" ); - Lenghts.push_back( static_cast( strlen( ShaderStrings.back() ) ) ); + + ShaderStrings.push_back(Settings.c_str()); + Lenghts.push_back( static_cast( Settings.length() ) ); const Char* ShaderTypeDefine = nullptr; switch( m_Desc.ShaderType ) @@ -148,7 +157,7 @@ ShaderGLImpl::ShaderGLImpl(FixedBlockMemoryAllocator& ShaderObjAllocator, Render Lenghts.push_back( static_cast( UserDefines.length() ) ); } - RefCntAutoPtr pFileData(new Diligent::DataBlobImpl); + RefCntAutoPtr pFileData(MakeNewRCObj()(0)); auto ShaderSource = ShaderCreationAttribs.Source; GLuint SourceLen = 0; if( ShaderSource ) @@ -160,6 +169,9 @@ ShaderGLImpl::ShaderGLImpl(FixedBlockMemoryAllocator& ShaderObjAllocator, Render VERIFY(ShaderCreationAttribs.pShaderSourceStreamFactory, "Input stream factory is null"); RefCntAutoPtr pSourceStream; ShaderCreationAttribs.pShaderSourceStreamFactory->CreateInputStream( ShaderCreationAttribs.FilePath, &pSourceStream ); + if (pSourceStream == nullptr) + LOG_ERROR_AND_THROW("Failed to open shader source file") + pSourceStream->Read( pFileData ); ShaderSource = reinterpret_cast(pFileData->GetDataPtr()); SourceLen = static_cast( pFileData->GetSize() ); @@ -168,13 +180,18 @@ ShaderGLImpl::ShaderGLImpl(FixedBlockMemoryAllocator& ShaderObjAllocator, Render 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( GLSLDefinitionsLen ) ); - // Convert HLSL to GLSL - HLSL2GLSLConverter Converter(ShaderCreationAttribs.pShaderSourceStreamFactory); - ConvertedSource = Converter.Convert(ShaderSource, SourceLen, ShaderCreationAttribs.EntryPoint, ShaderCreationAttribs.Desc.ShaderType); + const auto &Converter = HLSL2GLSLConverterImpl::GetInstance(); + HLSL2GLSLConverterImpl::ConversionAttribs Attribs; + Attribs.pSourceStreamFactory = ShaderCreationAttribs.pShaderSourceStreamFactory; + Attribs.ppConversionStream = ShaderCreationAttribs.ppConversionStream; + Attribs.HLSLSource = ShaderSource; + Attribs.NumSymbols = SourceLen; + Attribs.EntryPoint = ShaderCreationAttribs.EntryPoint; + Attribs.ShaderType = ShaderCreationAttribs.Desc.ShaderType; + Attribs.IncludeDefinitions = true; + Attribs.InputFileName = ShaderCreationAttribs.FilePath; + ConvertedSource = Converter.Convert(Attribs); ShaderSource = ConvertedSource.c_str(); SourceLen = static_cast( ConvertedSource.length() ); diff --git a/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp index c209e76a..961975ea 100644 --- a/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp @@ -30,8 +30,8 @@ namespace Diligent { -ShaderResourceBindingGLImpl::ShaderResourceBindingGLImpl( FixedBlockMemoryAllocator& SRBAllocator, PipelineStateGLImpl *pPSO) : - TBase( SRBAllocator, pPSO ), +ShaderResourceBindingGLImpl::ShaderResourceBindingGLImpl( IReferenceCounters *pRefCounters, PipelineStateGLImpl *pPSO) : + TBase( pRefCounters, pPSO ), m_DummyShaderVar(*this), m_wpPSO(pPSO) { diff --git a/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp index 69373f90..d067db7b 100644 --- a/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp @@ -28,11 +28,11 @@ namespace Diligent { -SwapChainGLImpl::SwapChainGLImpl(IMemoryAllocator &Allocator, +SwapChainGLImpl::SwapChainGLImpl(IReferenceCounters *pRefCounters, const SwapChainDesc& SCDesc, RenderDeviceGLImpl* pRenderDeviceGL, DeviceContextGLImpl* pImmediateContextGL) : - TSwapChainBase( Allocator, pRenderDeviceGL, pImmediateContextGL, pRenderDeviceGL->m_GLContext.GetSwapChainDesc() ) + TSwapChainBase( pRefCounters, pRenderDeviceGL, pImmediateContextGL, pRenderDeviceGL->m_GLContext.GetSwapChainDesc() ) { } diff --git a/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp b/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp index 73c64ff7..a790c978 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp @@ -58,13 +58,8 @@ namespace Diligent "} \n" }; - TexRegionRender::TexRegionRender( class RenderDeviceGLImpl *pDeviceGL ) : - m_OrigStencilRef(0), - m_NumRenderTargets(0) + TexRegionRender::TexRegionRender( class RenderDeviceGLImpl *pDeviceGL ) { - 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; @@ -94,6 +89,7 @@ namespace Diligent //CoordDim[RESOURCE_DIM_TEX_CUBE_ARRAY] = "ivec2(gl_FragCoord.xy)"; BufferDesc CBDesc; + CBDesc.Name = "TexRegionRender: FS constants CB"; CBDesc.uiSizeInBytes = sizeof(Int32)*4; CBDesc.Usage = USAGE_DYNAMIC; CBDesc.BindFlags = BIND_UNIFORM_BUFFER; @@ -194,7 +190,7 @@ namespace Diligent Int32 SrcMipLevel) { { - MapHelper< int > pConstant( pCtxGL, m_pConstantBuffer, MAP_WRITE_DISCARD, 0 ); + MapHelper< int > pConstant( pCtxGL, m_pConstantBuffer, MAP_WRITE, MAP_FLAG_DISCARD ); pConstant[0] = DstToSrcXOffset; pConstant[1] = DstToSrcYOffset; pConstant[2] = SrcZ; @@ -215,8 +211,10 @@ namespace Diligent } pCtxGL->SetPipelineState(m_pPSO[FSInd]); + // Technically resetting static varaibles is not allowed, but in GL this is OK auto SrcTexVar = m_pFragmentShaders[FSInd]->GetShaderVariable( "gSourceTex" ); SrcTexVar->Set( pSrcSRV ); + pCtxGL->CommitShaderResources(nullptr, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES); DrawAttribs DrawAttrs; DrawAttrs.NumVertices = 4; diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture1DArray_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture1DArray_OGL.cpp index 3446cb3a..efd522f0 100644 --- a/Graphics/GraphicsEngineOpenGL/src/Texture1DArray_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/Texture1DArray_OGL.cpp @@ -27,19 +27,20 @@ #include "RenderDeviceGLImpl.h" #include "DeviceContextGLImpl.h" #include "GLTypeConversions.h" - +#include "BufferGLImpl.h" namespace Diligent { -Texture1DArray_OGL::Texture1DArray_OGL( FixedBlockMemoryAllocator& TexObjAllocator, +Texture1DArray_OGL::Texture1DArray_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceGLImpl *pDeviceGL, - class DeviceContextGLImpl *pDeviceContext, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, const TextureDesc& TexDesc, const TextureData &InitData /*= TextureData()*/, bool bIsDeviceInternal /*= false*/) : - TextureBaseGL(TexObjAllocator, TexViewObjAllocator, pDeviceGL, TexDesc, GL_TEXTURE_1D_ARRAY, InitData, bIsDeviceInternal) + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, TexDesc, + GL_TEXTURE_1D_ARRAY, InitData, bIsDeviceInternal) { auto &ContextState = pDeviceContext->GetContextState(); @@ -84,6 +85,17 @@ Texture1DArray_OGL::Texture1DArray_OGL( FixedBlockMemoryAllocator& TexObjAllocat ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj( false ) ); } +Texture1DArray_OGL::Texture1DArray_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, + bool bIsDeviceInternal) : + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, pDeviceContext, TexDesc, GLTextureHandle, GL_TEXTURE_1D_ARRAY, bIsDeviceInternal) +{ +} + Texture1DArray_OGL::~Texture1DArray_OGL() { } @@ -95,12 +107,20 @@ void Texture1DArray_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, ContextState.BindTexture( -1, m_BindTarget, m_GlTexture ); + // Bind buffer if it is provided; copy from CPU memory otherwise + GLuint UnpackBuffer = 0; + if (SubresData.pSrcBuffer != nullptr) + { + auto *pBufferGL = ValidatedCast(SubresData.pSrcBuffer); + UnpackBuffer = pBufferGL->GetGLHandle(); + } + // 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); + // operations will be performed from this buffer. + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, UnpackBuffer); - auto TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); + const auto &TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); @@ -117,6 +137,9 @@ void Texture1DArray_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, CHECK_GL_ERROR("Failed to update subimage data"); + if(UnpackBuffer != 0) + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) ); } diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture1D_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture1D_OGL.cpp index 4835c053..96e1773b 100644 --- a/Graphics/GraphicsEngineOpenGL/src/Texture1D_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/Texture1D_OGL.cpp @@ -27,18 +27,19 @@ #include "RenderDeviceGLImpl.h" #include "DeviceContextGLImpl.h" #include "GLTypeConversions.h" +#include "BufferGLImpl.h" namespace Diligent { -Texture1D_OGL::Texture1D_OGL( FixedBlockMemoryAllocator& TexObjAllocator, +Texture1D_OGL::Texture1D_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceGLImpl *pDeviceGL, - class DeviceContextGLImpl *pDeviceContext, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, const TextureDesc& TexDesc, const TextureData &InitData /*= TextureData()*/, bool bIsDeviceInternal /*= false*/) : - TextureBaseGL(TexObjAllocator, TexViewObjAllocator, pDeviceGL, TexDesc, GL_TEXTURE_1D, InitData, bIsDeviceInternal) + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, TexDesc, GL_TEXTURE_1D, InitData, bIsDeviceInternal) { auto *pDeviceContextGL = ValidatedCast(pDeviceContext); auto &ContextState = pDeviceContextGL->GetContextState(); @@ -81,6 +82,17 @@ Texture1D_OGL::Texture1D_OGL( FixedBlockMemoryAllocator& TexObjAllocator, ContextState.BindTexture(-1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) ); } +Texture1D_OGL::Texture1D_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, + bool bIsDeviceInternal) : + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, pDeviceContext, TexDesc, GLTextureHandle, GL_TEXTURE_1D, bIsDeviceInternal) +{ +} + Texture1D_OGL::~Texture1D_OGL() { } @@ -92,12 +104,20 @@ void Texture1D_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint3 ContextState.BindTexture( -1, m_BindTarget, m_GlTexture ); + // Bind buffer if it is provided; copy from CPU memory otherwise + GLuint UnpackBuffer = 0; + if (SubresData.pSrcBuffer != nullptr) + { + auto *pBufferGL = ValidatedCast(SubresData.pSrcBuffer); + UnpackBuffer = pBufferGL->GetGLHandle(); + } + // 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); + // operations will be performed from this buffer. + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, UnpackBuffer); - auto TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); + const auto &TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); @@ -111,6 +131,9 @@ void Texture1D_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint3 SubresData.pData); CHECK_GL_ERROR("Failed to update subimage data"); + if(UnpackBuffer != 0) + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) ); } diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture2DArray_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture2DArray_OGL.cpp index dce1e2dc..b199439d 100644 --- a/Graphics/GraphicsEngineOpenGL/src/Texture2DArray_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/Texture2DArray_OGL.cpp @@ -28,18 +28,19 @@ #include "DeviceContextGLImpl.h" #include "GLTypeConversions.h" #include "GraphicsUtilities.h" +#include "BufferGLImpl.h" namespace Diligent { -Texture2DArray_OGL::Texture2DArray_OGL( FixedBlockMemoryAllocator& TexObjAllocator, +Texture2DArray_OGL::Texture2DArray_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceGLImpl *pDeviceGL, - class DeviceContextGLImpl *pDeviceContext, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, const TextureDesc& TexDesc, const TextureData &InitData /*= TextureData()*/, bool bIsDeviceInternal /*= false*/) : - TextureBaseGL(TexObjAllocator, TexViewObjAllocator, pDeviceGL, TexDesc, TexDesc.SampleCount > 1 ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY, InitData, bIsDeviceInternal) + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, TexDesc, TexDesc.SampleCount > 1 ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY, InitData, bIsDeviceInternal) { auto &ContextState = pDeviceContext->GetContextState(); ContextState.BindTexture(-1, m_BindTarget, m_GlTexture); @@ -104,23 +105,43 @@ Texture2DArray_OGL::Texture2DArray_OGL( FixedBlockMemoryAllocator& TexObjAllocat ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) ); } +Texture2DArray_OGL::Texture2DArray_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, + bool bIsDeviceInternal) : + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, pDeviceContext, TexDesc, GLTextureHandle, + TexDesc.SampleCount > 1 ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY, bIsDeviceInternal) +{ +} + Texture2DArray_OGL::~Texture2DArray_OGL() { } -void Texture2DArray_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData ) +void Texture2DArray_OGL::UpdateData(IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData) { auto &ContextState = ValidatedCast(pContext)->GetContextState(); TextureBaseGL::UpdateData(ContextState, pContext, MipLevel, Slice, DstBox, SubresData); ContextState.BindTexture(-1, m_BindTarget, m_GlTexture); + // Bind buffer if it is provided; copy from CPU memory otherwise + GLuint UnpackBuffer = 0; + if (SubresData.pSrcBuffer != nullptr) + { + auto *pBufferGL = ValidatedCast(SubresData.pSrcBuffer); + UnpackBuffer = pBufferGL->GetGLHandle(); + } + // 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); + // operations will be performed from this buffer. + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, UnpackBuffer); - auto TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); + const auto &TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); @@ -176,6 +197,9 @@ void Texture2DArray_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, } CHECK_GL_ERROR("Failed to update subimage data"); + if(UnpackBuffer != 0) + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) ); } diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture2D_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture2D_OGL.cpp index 4705795f..387a36c2 100644 --- a/Graphics/GraphicsEngineOpenGL/src/Texture2D_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/Texture2D_OGL.cpp @@ -28,18 +28,19 @@ #include "DeviceContextGLImpl.h" #include "GLTypeConversions.h" #include "GraphicsUtilities.h" +#include "BufferGLImpl.h" namespace Diligent { -Texture2D_OGL::Texture2D_OGL( FixedBlockMemoryAllocator& TexObjAllocator, +Texture2D_OGL::Texture2D_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceGLImpl *pDeviceGL, - class DeviceContextGLImpl *pDeviceContext, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, const TextureDesc& TexDesc, const TextureData &InitData /*= TextureData()*/, bool bIsDeviceInternal /*= false*/) : - TextureBaseGL(TexObjAllocator, TexViewObjAllocator, pDeviceGL, TexDesc, TexDesc.SampleCount > 1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, InitData, bIsDeviceInternal) + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, TexDesc, TexDesc.SampleCount > 1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, InitData, bIsDeviceInternal) { auto &ContextState = pDeviceContext->GetContextState(); ContextState.BindTexture(-1, m_BindTarget, m_GlTexture); @@ -102,6 +103,18 @@ Texture2D_OGL::Texture2D_OGL( FixedBlockMemoryAllocator& TexObjAllocator, ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) ); } +Texture2D_OGL::Texture2D_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, + bool bIsDeviceInternal) : + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, pDeviceContext, TexDesc, GLTextureHandle, + TexDesc.SampleCount > 1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, bIsDeviceInternal) +{ +} + Texture2D_OGL::~Texture2D_OGL() { } @@ -113,12 +126,20 @@ void Texture2D_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint3 ContextState.BindTexture(-1, m_BindTarget, m_GlTexture); + // Bind buffer if it is provided; copy from CPU memory otherwise + GLuint UnpackBuffer = 0; + if (SubresData.pSrcBuffer != nullptr) + { + auto *pBufferGL = ValidatedCast(SubresData.pSrcBuffer); + UnpackBuffer = pBufferGL->GetGLHandle(); + } + // 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); + // operations will be performed from this buffer. + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, UnpackBuffer); - auto TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); + const auto &TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); @@ -170,6 +191,9 @@ void Texture2D_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint3 } CHECK_GL_ERROR("Failed to update subimage data"); + if(UnpackBuffer != 0) + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) ); } diff --git a/Graphics/GraphicsEngineOpenGL/src/Texture3D_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/Texture3D_OGL.cpp index 2d45f91f..a6fb1544 100644 --- a/Graphics/GraphicsEngineOpenGL/src/Texture3D_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/Texture3D_OGL.cpp @@ -28,18 +28,20 @@ #include "DeviceContextGLImpl.h" #include "GLTypeConversions.h" #include "GraphicsUtilities.h" +#include "BufferGLImpl.h" namespace Diligent { -Texture3D_OGL::Texture3D_OGL( FixedBlockMemoryAllocator& TexObjAllocator, +Texture3D_OGL::Texture3D_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceGLImpl *pDeviceGL, - class DeviceContextGLImpl *pDeviceContext, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, const TextureDesc& TexDesc, const TextureData &InitData /*= TextureData()*/, bool bIsDeviceInternal /*= false*/) : - TextureBaseGL(TexObjAllocator, TexViewObjAllocator, pDeviceGL, TexDesc, GL_TEXTURE_3D, InitData, bIsDeviceInternal) + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, TexDesc, + GL_TEXTURE_3D, InitData, bIsDeviceInternal) { auto &ContextState = pDeviceContext->GetContextState(); ContextState.BindTexture(-1, m_BindTarget, m_GlTexture); @@ -83,6 +85,17 @@ Texture3D_OGL::Texture3D_OGL( FixedBlockMemoryAllocator& TexObjAllocator, ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) ); } +Texture3D_OGL::Texture3D_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, + bool bIsDeviceInternal) : + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, pDeviceContext, TexDesc, GLTextureHandle, GL_TEXTURE_3D, bIsDeviceInternal) +{ +} + Texture3D_OGL::~Texture3D_OGL() { } @@ -95,12 +108,20 @@ void Texture3D_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint3 ContextState.BindTexture(-1, m_BindTarget, m_GlTexture); + // Bind buffer if it is provided; copy from CPU memory otherwise + GLuint UnpackBuffer = 0; + if (SubresData.pSrcBuffer != nullptr) + { + auto *pBufferGL = ValidatedCast(SubresData.pSrcBuffer); + UnpackBuffer = pBufferGL->GetGLHandle(); + } + // 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); + // operations will be performed from this buffer. + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, UnpackBuffer); - auto TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); + const auto &TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); @@ -127,6 +148,9 @@ void Texture3D_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint3 CHECK_GL_ERROR("Failed to update subimage data"); + if(UnpackBuffer != 0) + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) ); } diff --git a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp index b5c1ec71..92f1ebdd 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp @@ -30,17 +30,18 @@ #include "GLContextState.h" #include "DeviceContextGLImpl.h" #include "EngineMemory.h" +#include "GraphicsUtilities.h" namespace Diligent { -TextureBaseGL::TextureBaseGL(FixedBlockMemoryAllocator& TexObjAllocator, +TextureBaseGL::TextureBaseGL(IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceGLImpl *pDeviceGL, + RenderDeviceGLImpl *pDeviceGL, const TextureDesc& TexDesc, GLenum BindTarget, const TextureData &InitData /*= TextureData()*/, bool bIsDeviceInternal /*= false*/) : - TTextureBase( TexObjAllocator, TexViewObjAllocator, pDeviceGL, TexDesc, bIsDeviceInternal ), + TTextureBase( pRefCounters, TexViewObjAllocator, pDeviceGL, TexDesc, bIsDeviceInternal ), m_GlTexture(true), // Create Texture immediately m_BindTarget(BindTarget), m_GLTexFormat( TexFormatToGLInternalTexFormat(m_Desc.Format, m_Desc.BindFlags) ) @@ -51,6 +52,97 @@ TextureBaseGL::TextureBaseGL(FixedBlockMemoryAllocator& TexObjAllocator, LOG_ERROR_AND_THROW("Static Texture must be initialized with data at creation time"); } +static GLenum GetTextureInternalFormat(DeviceContextGLImpl *pDeviceContextGL, GLenum BindTarget, const GLObjectWrappers::GLTextureObj& GLTex) +{ + auto &ContextState = pDeviceContextGL->GetContextState(); + ContextState.BindTexture(-1, BindTarget, GLTex); + + GLenum QueryBindTarget = BindTarget; + if (BindTarget == GL_TEXTURE_CUBE_MAP || BindTarget == GL_TEXTURE_CUBE_MAP_ARRAY) + QueryBindTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; + + GLint GlFormat = 0; + glGetTexLevelParameteriv(QueryBindTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &GlFormat); + CHECK_GL_ERROR( "Failed to get texture format through glGetTexLevelParameteriv()" ); + VERIFY(GlFormat != 0, "Unable to get texture format") + + ContextState.BindTexture(-1, BindTarget, GLObjectWrappers::GLTextureObj(false) ); + + return GlFormat; +} + +static TextureDesc GetTextureDescFromGLHandle(DeviceContextGLImpl *pDeviceContextGL, TextureDesc TexDesc, GLuint GLHandle, GLenum BindTarget) +{ + auto &ContextState = pDeviceContextGL->GetContextState(); + + VERIFY(BindTarget != GL_TEXTURE_CUBE_MAP_ARRAY, "Cubemap arrays are not currently supported") + + GLObjectWrappers::GLTextureObj TmpGLTexWrapper(true, GLObjectWrappers::GLTextureCreateReleaseHelper(GLHandle)); + ContextState.BindTexture(-1, BindTarget, TmpGLTexWrapper); + + GLenum QueryBindTarget = BindTarget; + if (BindTarget == GL_TEXTURE_CUBE_MAP) + QueryBindTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; + + GLint TexWidth = 0, TexHeight = 0, TexDepth = 0; + glGetTexLevelParameteriv(QueryBindTarget, 0, GL_TEXTURE_WIDTH, &TexWidth); + if (TexDesc.Type >= RESOURCE_DIM_TEX_2D) + glGetTexLevelParameteriv(QueryBindTarget, 0, GL_TEXTURE_HEIGHT, &TexHeight); + else + TexHeight = 1; + + if (TexDesc.Type == RESOURCE_DIM_TEX_3D) + glGetTexLevelParameteriv(QueryBindTarget, 0, GL_TEXTURE_DEPTH, &TexDepth); + else + TexDepth = 1; + + GLint GlFormat = 0; + glGetTexLevelParameteriv(QueryBindTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &GlFormat); + CHECK_GL_ERROR( "Failed to get texture level 0 parameters through glGetTexLevelParameteriv()" ); + + VERIFY(GlFormat != 0, "Unable to get texture format") + if (TexDesc.Format != TEX_FORMAT_UNKNOWN) + VERIFY(static_cast(GlFormat) == TexFormatToGLInternalTexFormat(TexDesc.Format), "Specified texture format (", GetTextureFormatAttribs(TexDesc.Format).Name,") does not match GL texture internal format (", GlFormat, ")") + else + TexDesc.Format = GLInternalTexFormatToTexFormat(GlFormat); + + VERIFY_EXPR(TexWidth > 0 && TexHeight > 0 && TexDepth > 0); + VERIFY(TexDesc.Width == 0 || TexDesc.Width == static_cast(TexWidth), "Specified texture width (", TexDesc.Width, ") does not match the actual width (", TexWidth, ")"); + VERIFY(TexDesc.Height == 0 || TexDesc.Height == static_cast(TexHeight), "Specified texture height (", TexDesc.Height,") does not match the actual height (", TexHeight, ")"); + TexDesc.Width = static_cast(TexWidth); + TexDesc.Height = static_cast(TexHeight); + if (TexDesc.Type == RESOURCE_DIM_TEX_3D) + { + VERIFY(TexDesc.Depth == 0 || TexDesc.Depth == static_cast(TexDepth), "Specified texture depth (", TexDesc.Depth, ") does not match the actual depth (", TexDepth, ")"); + TexDesc.Depth = static_cast(TexDepth); + } + + GLint MipLevels = 0; + glGetTexParameteriv(BindTarget, GL_TEXTURE_IMMUTABLE_LEVELS, &MipLevels); + CHECK_GL_ERROR( "Failed to get texture parameters through glGetTexParameteriv()" ); + VERIFY(TexDesc.MipLevels == 0 || TexDesc.MipLevels == static_cast(MipLevels), "Specified number of mip levels (", TexDesc.MipLevels, ") does not match the actual number of mip levels (", MipLevels, ")"); + TexDesc.MipLevels = static_cast(MipLevels); + + ContextState.BindTexture(-1, BindTarget, GLObjectWrappers::GLTextureObj(false) ); + return TexDesc; +} + +TextureBaseGL::TextureBaseGL(IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, + GLenum BindTarget, + bool bIsDeviceInternal/* = false*/) : + TTextureBase( pRefCounters, TexViewObjAllocator, pDeviceGL, GetTextureDescFromGLHandle(pDeviceContext, TexDesc, GLTextureHandle, BindTarget), bIsDeviceInternal ), + // Create texture object wrapper, but use external texture handle + m_GlTexture(true, GLObjectWrappers::GLTextureCreateReleaseHelper(GLTextureHandle)), + m_BindTarget(BindTarget), + m_GLTexFormat( GetTextureInternalFormat(pDeviceContext, BindTarget, m_GlTexture) ) +{ +} + TextureBaseGL::~TextureBaseGL() { // Release all FBOs that contain current texture @@ -58,7 +150,7 @@ TextureBaseGL::~TextureBaseGL() // flag is set, because CopyData() can bind // texture as render target even when no flag // is set - static_cast( GetDevice() )->m_FBOCache.OnReleaseTexture(this); + static_cast( GetDevice() )->OnReleaseTexture(this); } IMPLEMENT_QUERY_INTERFACE( TextureBaseGL, IID_TextureGL, TTextureBase ) @@ -90,14 +182,14 @@ void TextureBaseGL::CreateViewInternal( const struct TextureViewDesc &OrigViewDe if( ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE ) { bool bIsFullTextureView = - ViewDesc.TextureDim == m_Desc.Type && - ViewDesc.Format == CorrectTextureViewFormat( m_Desc.Format, ViewDesc.ViewType ) && + ViewDesc.TextureDim == m_Desc.Type && + ViewDesc.Format == GetDefaultTextureViewFormat( m_Desc.Format, ViewDesc.ViewType, m_Desc.BindFlags ) && ViewDesc.MostDetailedMip == 0 && ViewDesc.NumMipLevels == m_Desc.MipLevels && ViewDesc.FirstArraySlice == 0 && ViewDesc.NumArraySlices == m_Desc.ArraySize; - pViewOGL = NEW(TexViewAllocator, "TextureViewGLImpl instance", TextureViewGLImpl, + pViewOGL = NEW_RC_OBJ(TexViewAllocator, "TextureViewGLImpl instance", TextureViewGLImpl, bIsDefaultView ? this : nullptr)( pDeviceGLImpl, ViewDesc, this, !bIsFullTextureView, // Create OpenGL texture view object if view // does not address the whole texture @@ -143,6 +235,7 @@ void TextureBaseGL::CreateViewInternal( const struct TextureViewDesc &OrigViewDe 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" ); + pViewOGL->SetBindTarget(GLViewTarget); } } else if( ViewDesc.ViewType == TEXTURE_VIEW_UNORDERED_ACCESS ) @@ -150,7 +243,7 @@ void TextureBaseGL::CreateViewInternal( const struct TextureViewDesc &OrigViewDe 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(TexViewAllocator, "TextureViewGLImpl instance", TextureViewGLImpl, + pViewOGL = NEW_RC_OBJ(TexViewAllocator, "TextureViewGLImpl instance", TextureViewGLImpl, bIsDefaultView ? this : nullptr)( pDeviceGLImpl, ViewDesc, this, false, // Do NOT create texture view OpenGL object bIsDefaultView @@ -159,7 +252,7 @@ void TextureBaseGL::CreateViewInternal( const struct TextureViewDesc &OrigViewDe else if( ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET ) { VERIFY( ViewDesc.NumMipLevels == 1, "Only single mip level can be bound as RTV" ); - pViewOGL = NEW(TexViewAllocator, "TextureViewGLImpl instance", TextureViewGLImpl, + pViewOGL = NEW_RC_OBJ(TexViewAllocator, "TextureViewGLImpl instance", TextureViewGLImpl, bIsDefaultView ? this : nullptr)( pDeviceGLImpl, ViewDesc, this, false, // Do NOT create texture view OpenGL object bIsDefaultView @@ -168,7 +261,7 @@ void TextureBaseGL::CreateViewInternal( const struct TextureViewDesc &OrigViewDe else if( ViewDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL ) { VERIFY( ViewDesc.NumMipLevels == 1, "Only single mip level can be bound as DSV" ); - pViewOGL = NEW(TexViewAllocator, "TextureViewGLImpl instance", TextureViewGLImpl, + pViewOGL = NEW_RC_OBJ(TexViewAllocator, "TextureViewGLImpl instance", TextureViewGLImpl, bIsDefaultView ? this : nullptr)( pDeviceGLImpl, ViewDesc, this, false, // Do NOT create texture view OpenGL object bIsDefaultView @@ -253,10 +346,10 @@ void TextureBaseGL :: CopyData(IDeviceContext *pContext, 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; + GLint SrcSliceY = (SrcTexDesc.Type == RESOURCE_DIM_TEX_1D_ARRAY) ? SrcSlice : 0; + GLint SrcSliceZ = (SrcTexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY) ? SrcSlice : 0; + GLint DstSliceY = (m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY) ? DstSlice : 0; + GLint DstSliceZ = (m_Desc.Type == RESOURCE_DIM_TEX_2D_ARRAY) ? DstSlice : 0; glCopyImageSubData( pSrcTextureGL->GetGLHandle(), pSrcTextureGL->GetBindTarget(), @@ -288,7 +381,6 @@ void TextureBaseGL :: CopyData(IDeviceContext *pContext, auto &TexViewObjAllocator = pRenderDeviceGL->GetTexViewObjAllocator(); VERIFY( &TexViewObjAllocator == &m_dbgTexViewObjAllocator, "Texture view allocator does not match allocator provided during texture initialization" ); - auto &FBOCache = pRenderDeviceGL->m_FBOCache; auto &TexRegionRender = pRenderDeviceGL->m_TexRegionRender; TexRegionRender.SetStates(pDeviceCtxGL); @@ -300,7 +392,7 @@ void TextureBaseGL :: CopyData(IDeviceContext *pContext, // Note: texture view allocates memory for the copy of the name // If the name is empty, memory should not be allocated // We have to provide allocator even though it will never be used - TextureViewGLImpl SRV( TexViewObjAllocator, GetDevice(), SRVDesc, pSrcTextureGL, + TextureViewGLImpl SRV( GetReferenceCounters(), 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 @@ -319,7 +411,7 @@ void TextureBaseGL :: CopyData(IDeviceContext *pContext, // Note: texture view allocates memory for the copy of the name // If the name is empty, memory should not be allocated // We have to provide allocator even though it will never be used - TextureViewGLImpl RTV( TexViewObjAllocator, GetDevice(), RTVDesc, this, + TextureViewGLImpl RTV( GetReferenceCounters(), 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 @@ -328,12 +420,7 @@ void TextureBaseGL :: CopyData(IDeviceContext *pContext, ITextureView *pRTVs[] = { &RTV }; pDeviceCtxGL->SetRenderTargets( _countof( pRTVs ), pRTVs, nullptr ); - Viewport VP; - VP.TopLeftX = static_cast( DstX ); - VP.TopLeftY = static_cast( DstY ); - VP.Width = static_cast(pSrcBox->MaxX - pSrcBox->MinX); - VP.Height = static_cast(pSrcBox->MaxY - pSrcBox->MinY); - pDeviceCtxGL->SetViewports( 1, &VP, 0, 0 ); + // No need to set up the viewport as SetRenderTargets() does that TexRegionRender.Render( pDeviceCtxGL, &SRV, @@ -350,65 +437,16 @@ void TextureBaseGL :: CopyData(IDeviceContext *pContext, } -void TextureBaseGL :: Map(IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapFlags, PVoid &pMappedData) +void TextureBaseGL :: Map(IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource &MappedData) { - 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); + TTextureBase::Map( pContext, Subresource, MapType, MapFlags, MappedData ); + LOG_ERROR_MESSAGE("Texture mapping is not supported in OpenGL") } -void TextureBaseGL::Unmap( IDeviceContext *pContext, MAP_TYPE MapType ) +void TextureBaseGL::Unmap( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags ) { - TTextureBase::Unmap(pContext, MapType); - - //glBindTexture(m_uiMapTarget, m_GlTexture); - //glUnmapTexture(m_uiMapTarget); - //glBindTexture(m_uiMapTarget, 0); - //m_uiMapTarget = 0; + TTextureBase::Unmap(pContext, Subresource, MapType, MapFlags); + LOG_ERROR_MESSAGE("Texture mapping is not supported in OpenGL") } void TextureBaseGL::TextureMemoryBarrier( Uint32 RequiredBarriers, GLContextState &GLContextState ) @@ -445,7 +483,7 @@ void TextureBaseGL::SetDefaultGLParameters() } 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" ); + VERIFY( static_cast(BoundTex) == m_GlTexture, "Current texture is not bound to GL context" ); #endif if( m_BindTarget != GL_TEXTURE_2D_MULTISAMPLE && diff --git a/Graphics/GraphicsEngineOpenGL/src/TextureCubeArray_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureCubeArray_OGL.cpp index 3658b7d9..e49b1a8c 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TextureCubeArray_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TextureCubeArray_OGL.cpp @@ -28,18 +28,19 @@ #include "DeviceContextGLImpl.h" #include "GLTypeConversions.h" #include "GraphicsUtilities.h" +#include "BufferGLImpl.h" namespace Diligent { -TextureCubeArray_OGL::TextureCubeArray_OGL( FixedBlockMemoryAllocator& TexObjAllocator, +TextureCubeArray_OGL::TextureCubeArray_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceGLImpl *pDeviceGL, - class DeviceContextGLImpl *pDeviceContext, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, const TextureDesc& TexDesc, const TextureData &InitData /*= TextureData()*/, bool bIsDeviceInternal /*= false*/) : - TextureBaseGL(TexObjAllocator, TexViewObjAllocator, pDeviceGL, TexDesc, GL_TEXTURE_CUBE_MAP_ARRAY, InitData, bIsDeviceInternal) + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, TexDesc, GL_TEXTURE_CUBE_MAP_ARRAY, InitData, bIsDeviceInternal) { VERIFY(m_Desc.SampleCount == 1, "Multisampled texture cube arrays are not supported") @@ -91,6 +92,17 @@ TextureCubeArray_OGL::TextureCubeArray_OGL( FixedBlockMemoryAllocator& TexObjAll ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) ); } +TextureCubeArray_OGL::TextureCubeArray_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, + bool bIsDeviceInternal) : + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, pDeviceContext, TexDesc, GLTextureHandle, GL_TEXTURE_CUBE_MAP_ARRAY, bIsDeviceInternal) +{ +} + TextureCubeArray_OGL::~TextureCubeArray_OGL() { } @@ -102,12 +114,20 @@ void TextureCubeArray_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel ContextState.BindTexture(-1, m_BindTarget, m_GlTexture); + // Bind buffer if it is provided; copy from CPU memory otherwise + GLuint UnpackBuffer = 0; + if (SubresData.pSrcBuffer != nullptr) + { + auto *pBufferGL = ValidatedCast(SubresData.pSrcBuffer); + UnpackBuffer = pBufferGL->GetGLHandle(); + } + // 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); + // operations will be performed from this buffer. + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, UnpackBuffer); - auto TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); + const auto &TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); @@ -173,6 +193,9 @@ void TextureCubeArray_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel } CHECK_GL_ERROR("Failed to update subimage data"); + if(UnpackBuffer != 0) + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) ); } diff --git a/Graphics/GraphicsEngineOpenGL/src/TextureCube_OGL.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureCube_OGL.cpp index 2d7f4362..46de7e76 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TextureCube_OGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TextureCube_OGL.cpp @@ -28,18 +28,19 @@ #include "DeviceContextGLImpl.h" #include "GLTypeConversions.h" #include "GraphicsUtilities.h" +#include "BufferGLImpl.h" namespace Diligent { -TextureCube_OGL::TextureCube_OGL( FixedBlockMemoryAllocator& TexObjAllocator, +TextureCube_OGL::TextureCube_OGL( IReferenceCounters *pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, class RenderDeviceGLImpl *pDeviceGL, class DeviceContextGLImpl *pDeviceContext, const TextureDesc& TexDesc, const TextureData &InitData /*= TextureData()*/, bool bIsDeviceInternal /*= false*/) : - TextureBaseGL(TexObjAllocator, TexViewObjAllocator, pDeviceGL, TexDesc, GL_TEXTURE_CUBE_MAP, InitData, bIsDeviceInternal) + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, TexDesc, GL_TEXTURE_CUBE_MAP, InitData, bIsDeviceInternal) { VERIFY(m_Desc.SampleCount == 1, "Multisampled cubemap textures are not supported"); @@ -89,6 +90,17 @@ TextureCube_OGL::TextureCube_OGL( FixedBlockMemoryAllocator& TexObjAllocator, ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) ); } +TextureCube_OGL::TextureCube_OGL( IReferenceCounters *pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + RenderDeviceGLImpl *pDeviceGL, + DeviceContextGLImpl *pDeviceContext, + const TextureDesc& TexDesc, + GLuint GLTextureHandle, + bool bIsDeviceInternal) : + TextureBaseGL(pRefCounters, TexViewObjAllocator, pDeviceGL, pDeviceContext, TexDesc, GLTextureHandle, GL_TEXTURE_CUBE_MAP, bIsDeviceInternal) +{ +} + TextureCube_OGL::~TextureCube_OGL() { } @@ -116,12 +128,20 @@ void TextureCube_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uin auto CubeMapFaceBindTarget = CubeMapFaces[Slice]; + // Bind buffer if it is provided; copy from CPU memory otherwise + GLuint UnpackBuffer = 0; + if (SubresData.pSrcBuffer != nullptr) + { + auto *pBufferGL = ValidatedCast(SubresData.pSrcBuffer); + UnpackBuffer = pBufferGL->GetGLHandle(); + } + // 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); + // operations will be performed from this buffer. + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, UnpackBuffer); - auto TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); + const auto &TransferAttribs = GetNativePixelTransferAttribs(m_Desc.Format); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); @@ -178,6 +198,9 @@ void TextureCube_OGL::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uin } CHECK_GL_ERROR("Failed to update subimage data"); + if(UnpackBuffer != 0) + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + ContextState.BindTexture( -1, m_BindTarget, GLObjectWrappers::GLTextureObj(false) ); } diff --git a/Graphics/GraphicsEngineOpenGL/src/TextureViewGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureViewGLImpl.cpp index 483f4141..4fc821cd 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TextureViewGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TextureViewGLImpl.cpp @@ -30,13 +30,13 @@ namespace Diligent { - TextureViewGLImpl::TextureViewGLImpl( FixedBlockMemoryAllocator &TexViewObjAllocator, + TextureViewGLImpl::TextureViewGLImpl( IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const TextureViewDesc& ViewDesc, TextureBaseGL* pTexture, bool bCreateGLViewTex, bool bIsDefaultView ) : - TTextureViewBase(TexViewObjAllocator, pDevice, ViewDesc, pTexture, bIsDefaultView), + TTextureViewBase(pRefCounters, pDevice, ViewDesc, pTexture, bIsDefaultView), m_ViewTexGLHandle( bCreateGLViewTex ), m_ViewTexBindTarget(0) { diff --git a/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp b/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp index 3b4e9ef9..0a87619e 100644 --- a/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp @@ -34,7 +34,8 @@ namespace Diligent { -VAOCache::VAOCache() +VAOCache::VAOCache() : + m_EmptyVAO(true) { m_Cache.max_load_factor(0.5f); m_PSOToKey.max_load_factor(0.5f); @@ -79,7 +80,9 @@ const GLObjectWrappers::GLVertexArrayObj& VAOCache::GetVAO( IPipelineState *pPSO // Lock the cache ThreadingTools::LockHelper CacheLock(m_CacheLockFlag); - RefCntAutoPtr spVertexBuffers[MaxBufferSlots]; + IBuffer* VertexBuffers[MaxBufferSlots]; + for (Uint32 s = 0; s < NumVertexStreams; ++s) + VertexBuffers[s] = nullptr; // Get layout auto *pPSOGL = ValidatedCast(pPSO); @@ -89,58 +92,61 @@ const GLObjectWrappers::GLVertexArrayObj& VAOCache::GetVAO( IPipelineState *pPSO Uint32 NumElems = InputLayout.NumElements; const Uint32 *TightStrides = pPSOGL->GetTightStrides(); // Construct the key - VAOCacheKey Key = {0}; - Key.pPSO = pPSO; - Key.pIndexBuffer = pIndexBuffer; + VAOCacheKey Key(pPSO, pIndexBuffer); - auto LayoutIt = LayoutElems; - for( size_t Elem = 0; Elem < NumElems; ++Elem, ++LayoutIt ) { - auto BuffSlot = LayoutIt->BufferSlot; - if( BuffSlot >= NumVertexStreams ) - { - 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(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 + auto LayoutIt = LayoutElems; + for (size_t Elem = 0; Elem < NumElems; ++Elem, ++LayoutIt) { - 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" ); + auto BuffSlot = LayoutIt->BufferSlot; + if (BuffSlot >= NumVertexStreams) + { + UNEXPECTED("Input layout requires more buffers than bound to the pipeline"); + continue; + } + if (BuffSlot >= MaxBufferSlots) + { + VERIFY(BuffSlot >= MaxBufferSlots, "Incorrect input slot"); + continue; + } + auto MaxUsedSlot = std::max(Key.NumUsedSlots, BuffSlot + 1); + for (Uint32 s = Key.NumUsedSlots; s < MaxUsedSlot; ++s) + Key.Streams[s] = VAOCacheKey::StreamAttribs{}; + Key.NumUsedSlots = MaxUsedSlot; + + auto &CurrStream = VertexStreams[BuffSlot]; + auto Stride = CurrStream.Stride ? CurrStream.Stride : TightStrides[BuffSlot]; + auto &pCurrBuf = VertexBuffers[BuffSlot]; + auto &CurrStreamKey = Key.Streams[BuffSlot]; + if (pCurrBuf == nullptr) + { + pCurrBuf = CurrStream.pBuffer; + VERIFY(pCurrBuf != nullptr, "No buffer bound to slot ", BuffSlot); + + ValidatedCast(pCurrBuf)->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 = pCurrBuf; + CurrStreamKey.Stride = Stride; + CurrStreamKey.Offset = CurrStream.Offset; + } + else + { + VERIFY(pCurrBuf == CurrStream.pBuffer, "Buffer no longer exists"); + VERIFY(CurrStreamKey.pBuffer == pCurrBuf, "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(pIndexBuffer)->BufferMemoryBarrier( + ValidatedCast(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 @@ -174,9 +180,9 @@ const GLObjectWrappers::GLVertexArrayObj& VAOCache::GetVAO( IPipelineState *pPSO // 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( spBuff.RawPtr() ); + auto *pBuff = VertexBuffers[BuffSlot]; + VERIFY( pBuff != nullptr, "Vertex buffer is null" ); + const BufferGLImpl *pBufferOGL = static_cast( pBuff ); glBindBuffer(GL_ARRAY_BUFFER, pBufferOGL->m_GlBuffer); GLvoid* DataStartOffset = reinterpret_cast( static_cast( CurrStream.Offset + LayoutIt->RelativeOffset ) ); @@ -207,19 +213,24 @@ const GLObjectWrappers::GLVertexArrayObj& VAOCache::GetVAO( IPipelineState *pPSO glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pIndBufferOGL->m_GlBuffer); } - auto NewElems = m_Cache.emplace( make_pair(Key, std::move(NewVAO)) ); + auto NewElems = m_Cache.emplace( std::make_pair(Key, std::move(NewVAO)) ); // New element must be actually inserted VERIFY( NewElems.second, "New element was not inserted into the cache" ); - m_PSOToKey.insert( make_pair(Key.pPSO, Key) ); - for(int iStream = 0; iStream < _countof(Key.Streams); ++iStream) + m_PSOToKey.insert( std::make_pair(Key.pPSO, Key) ); + for(Uint32 Slot = 0; Slot < Key.NumUsedSlots; ++Slot) { - auto *pCurrBuff = Key.Streams[iStream].pBuffer; + auto *pCurrBuff = Key.Streams[Slot].pBuffer; if( pCurrBuff ) - m_BuffToKey.insert( make_pair(pCurrBuff, Key) ); + m_BuffToKey.insert( std::make_pair(pCurrBuff, Key) ); } return NewElems.first->second; } } +const GLObjectWrappers::GLVertexArrayObj& VAOCache::GetEmptyVAO() +{ + return m_EmptyVAO; +} + } -- cgit v1.2.3