summaryrefslogtreecommitdiffstats
path: root/Tests/TestApp/src
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-02-15 07:22:18 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-02-15 07:22:18 +0000
commit5c9450e283d0889987e39ebd13b5a29c110d9e88 (patch)
treefc8c9eb710106d57fe0f18816da9948d10ad7832 /Tests/TestApp/src
parentFixed formatting of cmake files + some minor updates (diff)
downloadDiligentEngine-5c9450e283d0889987e39ebd13b5a29c110d9e88.tar.gz
DiligentEngine-5c9450e283d0889987e39ebd13b5a29c110d9e88.zip
Added tests
Diffstat (limited to 'Tests/TestApp/src')
-rw-r--r--Tests/TestApp/src/AllocatorTest.cpp81
-rw-r--r--Tests/TestApp/src/Android/TestAppAndroid.cpp145
-rw-r--r--Tests/TestApp/src/CMakeLists.txt143
-rw-r--r--Tests/TestApp/src/IOS/TestAppIOS.cpp49
-rw-r--r--Tests/TestApp/src/Linux/TestAppLinux.cpp45
-rw-r--r--Tests/TestApp/src/MTResourceCreationTest.cpp247
-rw-r--r--Tests/TestApp/src/MacOS/TestAppMacOS.cpp47
-rw-r--r--Tests/TestApp/src/MathLibTest.cpp503
-rw-r--r--Tests/TestApp/src/RenderScriptTest.cpp424
-rw-r--r--Tests/TestApp/src/RingBufferTest.cpp132
-rw-r--r--Tests/TestApp/src/ShaderConverterTest.cpp73
-rw-r--r--Tests/TestApp/src/SmartPointerTest.cpp746
-rw-r--r--Tests/TestApp/src/TestApp.cpp493
-rw-r--r--Tests/TestApp/src/TestBlendState.cpp250
-rw-r--r--Tests/TestApp/src/TestBufferAccess.cpp266
-rw-r--r--Tests/TestApp/src/TestBufferCreation.cpp137
-rw-r--r--Tests/TestApp/src/TestComputeShaders.cpp50
-rw-r--r--Tests/TestApp/src/TestCopyTexData.cpp197
-rw-r--r--Tests/TestApp/src/TestCreateObjFromNativeResD3D11.cpp104
-rw-r--r--Tests/TestApp/src/TestCreateObjFromNativeResD3D12.cpp77
-rw-r--r--Tests/TestApp/src/TestCreateObjFromNativeResGL.cpp141
-rw-r--r--Tests/TestApp/src/TestDepthStencilState.cpp161
-rw-r--r--Tests/TestApp/src/TestDrawCommands.cpp964
-rw-r--r--Tests/TestApp/src/TestGeometryShader.cpp86
-rw-r--r--Tests/TestApp/src/TestPipelineStateBase.cpp65
-rw-r--r--Tests/TestApp/src/TestRasterizerState.cpp132
-rw-r--r--Tests/TestApp/src/TestRenderTarget.cpp54
-rw-r--r--Tests/TestApp/src/TestSamplerCreation.cpp129
-rw-r--r--Tests/TestApp/src/TestShaderResArrays.cpp190
-rw-r--r--Tests/TestApp/src/TestTessellation.cpp128
-rw-r--r--Tests/TestApp/src/TestTextureCreation.cpp953
-rw-r--r--Tests/TestApp/src/TestTexturing.cpp285
-rw-r--r--Tests/TestApp/src/TestVPAndSR.cpp49
-rw-r--r--Tests/TestApp/src/UWP/TestAppUWP.cpp209
-rw-r--r--Tests/TestApp/src/VarSizeAllocationsManagerTest.cpp178
-rw-r--r--Tests/TestApp/src/Win32/TestAppWin32.cpp39
-rw-r--r--Tests/TestApp/src/pch.cpp31
37 files changed, 8003 insertions, 0 deletions
diff --git a/Tests/TestApp/src/AllocatorTest.cpp b/Tests/TestApp/src/AllocatorTest.cpp
new file mode 100644
index 0000000..098317c
--- /dev/null
+++ b/Tests/TestApp/src/AllocatorTest.cpp
@@ -0,0 +1,81 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "AllocatorTest.h"
+#include "Errors.h"
+#include "DefaultRawMemoryAllocator.h"
+#include "FixedBlockMemoryAllocator.h"
+
+using namespace Diligent;
+
+AllocatorTest TheTest;
+
+AllocatorTest::AllocatorTest()
+{
+ const Uint32 AllocSize = 32;
+ const Uint32 NumAllocationsPerPage = 16;
+ FixedBlockMemoryAllocator TestAllocator(DefaultRawMemoryAllocator::GetAllocator(), AllocSize, NumAllocationsPerPage);
+ void* Allocations[NumAllocationsPerPage][2]={};
+ for(int p=0; p < 2; ++p)
+ {
+ for (int a = 1; a < NumAllocationsPerPage; ++a)
+ {
+ for (int i = 0; i < a; ++i)
+ Allocations[i][p] = TestAllocator.Allocate(AllocSize, "Fixed block allocator test", __FILE__, __LINE__);
+
+ for (int i = a-1; i >= 0; --i)
+ TestAllocator.Free(Allocations[i][p]);
+
+ for (int i = 0; i < a; ++i)
+ {
+ auto *NewAlloc = TestAllocator.Allocate(AllocSize, "Fixed block allocator test", __FILE__, __LINE__);
+ VERIFY_EXPR(Allocations[i][p] == NewAlloc);
+ }
+
+ for (int i = a-1; i >= 0; --i)
+ TestAllocator.Free(Allocations[i][p]);
+ }
+ for (int i = 0; i < NumAllocationsPerPage; ++i)
+ Allocations[i][p] = TestAllocator.Allocate(AllocSize, "Fixed block allocator test", __FILE__, __LINE__);
+ }
+
+ for(int p=0; p < 2; ++p)
+ for (int i = 0; i < NumAllocationsPerPage; ++i)
+ TestAllocator.Free( Allocations[i][p] );
+
+ for(int p=0; p < 2; ++p)
+ for (int i = 0; i < NumAllocationsPerPage; ++i)
+ Allocations[i][p] = TestAllocator.Allocate(AllocSize, "Fixed block allocator test", __FILE__, __LINE__);
+
+ for(int p=0; p < 2; ++p)
+ for (int s = 0; s < 5; ++s)
+ for (int i = s; i < NumAllocationsPerPage; i+=5)
+ TestAllocator.Free( Allocations[i][p] );
+
+ // Double free
+ //TestAllocator.Free( Allocations[0][0] );
+}
diff --git a/Tests/TestApp/src/Android/TestAppAndroid.cpp b/Tests/TestApp/src/Android/TestAppAndroid.cpp
new file mode 100644
index 0000000..0cd8eb1
--- /dev/null
+++ b/Tests/TestApp/src/Android/TestAppAndroid.cpp
@@ -0,0 +1,145 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+
+#include "SampleApp.h"
+#include "RenderDeviceGLES.h"
+#include "AntTweakBar.h"
+
+using namespace Diligent;
+
+class SampleAppAndroid final : public SampleApp
+{
+public:
+ SampleAppAndroid()
+ {
+ m_DeviceType = DeviceType::OpenGLES;
+ }
+
+ virtual void Initialize(ANativeWindow* window)override final
+ {
+ InitializeDiligentEngine(window);
+ m_RenderDeviceGLES = RefCntAutoPtr<IRenderDeviceGLES>(m_pDevice, IID_RenderDeviceGLES);
+ m_TheSample->SetUIScale(3);
+ InitializeSample();
+ }
+
+ virtual int Resume(ANativeWindow* window)override final
+ {
+ return m_RenderDeviceGLES->Resume(window);
+ }
+
+ virtual void TermDisplay()override final
+ {
+ // Tear down the EGL context currently associated with the display.
+ m_RenderDeviceGLES->Suspend();
+ }
+
+ virtual void TrimMemory()override final
+ {
+ LOGI( "Trimming memory" );
+ m_RenderDeviceGLES->Invalidate();
+ }
+
+ virtual int32_t HandleInput( AInputEvent* event )override final
+ {
+ if( AInputEvent_getType( event ) == AINPUT_EVENT_TYPE_MOTION )
+ {
+ ndk_helper::GESTURE_STATE doubleTapState = doubletap_detector_.Detect( event );
+ ndk_helper::GESTURE_STATE dragState = drag_detector_.Detect( event );
+ ndk_helper::GESTURE_STATE pinchState = pinch_detector_.Detect( event );
+
+ //Double tap detector has a priority over other detectors
+ if( doubleTapState == ndk_helper::GESTURE_STATE_ACTION )
+ {
+ //Detect double tap
+ //tap_camera_.Reset( true );
+ }
+ else
+ {
+ //Handle drag state
+ if( dragState & ndk_helper::GESTURE_STATE_START )
+ {
+ //Otherwise, start dragging
+ ndk_helper::Vec2 v;
+ drag_detector_.GetPointer( v );
+ float fX = 0, fY = 0;
+ v.Value(fX, fY);
+ TwMouseMotion((short)fX, (short)fY);
+ int Handled = TwMouseButton( TW_MOUSE_PRESSED, TW_MOUSE_LEFT );
+
+ //TransformPosition( v );
+ //tap_camera_.BeginDrag( v );
+ }
+ else if( dragState & ndk_helper::GESTURE_STATE_MOVE )
+ {
+ ndk_helper::Vec2 v;
+ drag_detector_.GetPointer( v );
+ float fX = 0, fY = 0;
+ v.Value(fX, fY);
+ int Handled = TwMouseMotion((short)fX, (short)fY);
+ //TransformPosition( v );
+ //tap_camera_.Drag( v );
+ }
+ else if( dragState & ndk_helper::GESTURE_STATE_END )
+ {
+ int Handled = TwMouseButton(TW_MOUSE_RELEASED, TW_MOUSE_LEFT);
+
+ //tap_camera_.EndDrag();
+ }
+
+ //Handle pinch state
+ if( pinchState & ndk_helper::GESTURE_STATE_START )
+ {
+ //Start new pinch
+ ndk_helper::Vec2 v1;
+ ndk_helper::Vec2 v2;
+ pinch_detector_.GetPointers( v1, v2 );
+ //TransformPosition( v1 );
+ //TransformPosition( v2 );
+ //tap_camera_.BeginPinch( v1, v2 );
+ }
+ else if( pinchState & ndk_helper::GESTURE_STATE_MOVE )
+ {
+ //Multi touch
+ //Start new pinch
+ ndk_helper::Vec2 v1;
+ ndk_helper::Vec2 v2;
+ pinch_detector_.GetPointers( v1, v2 );
+ //TransformPosition( v1 );
+ //TransformPosition( v2 );
+ //tap_camera_.Pinch( v1, v2 );
+ }
+ }
+ return 1;
+ }
+ return 0;
+ }
+
+private:
+ RefCntAutoPtr<IRenderDeviceGLES> m_RenderDeviceGLES;
+};
+
+NativeAppBase* CreateApplication()
+{
+ return new SampleAppAndroid;
+}
diff --git a/Tests/TestApp/src/CMakeLists.txt b/Tests/TestApp/src/CMakeLists.txt
new file mode 100644
index 0000000..1de4d2a
--- /dev/null
+++ b/Tests/TestApp/src/CMakeLists.txt
@@ -0,0 +1,143 @@
+cmake_minimum_required (VERSION 3.6)
+
+project(TestApp)
+
+file(GLOB SOURCE LIST_DIRECTORIES false Src/*.cpp)
+#set(SOURCE
+# src/TestApp.cpp
+#)
+
+set(INCLUDE
+ include/TestApp.h
+)
+
+set(SHADERS)
+
+set(ASSETS)
+
+set(ALL_ASSETS ${ASSETS} ${SHADERS})
+add_target_platform_app(TestApp "${SOURCE}" "${INCLUDE}" "${ALL_ASSETS}")
+
+if(PLATFORM_WIN32)
+ set(WIN32_SOURCE src/Win32/TestAppWin32.cpp)
+ target_sources(TestApp PRIVATE ${WIN32_SOURCE})
+ source_group("src\\Win32" FILES ${WIN32_SOURCE})
+
+ set_target_properties(TestApp PROPERTIES
+ VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets"
+ )
+ copy_required_dlls(TestApp)
+
+elseif(PLATFORM_UNIVERSAL_WINDOWS)
+
+ set(UWP_SOURCE
+ src/UWP/TestAppUWP.cpp
+ )
+ target_sources(TestApp PRIVATE ${UWP_SOURCE})
+ source_group("src\\UWP" FILES ${UWP_SOURCE})
+ target_include_directories(${TestApp} PRIVATE src/UWP)
+
+elseif(PLATFORM_ANDROID)
+ set(ANDROID_SOURCE
+ src/Android/TestAppAndroid.cpp
+ )
+ target_sources(TestApp PRIVATE ${ANDROID_SOURCE})
+ source_group("src\\Android" FILES ${ANDROID_SOURCE})
+elseif(PLATFORM_LINUX)
+ set(LINUX_SOURCE
+ src/Linux/TestAppLinux.cpp
+ )
+ target_sources(TestApp PRIVATE ${LINUX_SOURCE})
+ source_group("src\\Linux" FILES ${LINUX_SOURCE})
+elseif(PLATFORM_MACOS)
+
+ set(MAC_SOURCE
+ src/MacOS/TestAppMacOS.cpp
+ )
+ target_sources(TestApp PRIVATE ${MAC_SOURCE})
+ source_group("src\\McOS" FILES ${MAC_SOURCE})
+
+elseif(PLATFORM_IOS)
+ set(IOS_SOURCE
+ src/IOS/TestAppIOS.cpp
+ )
+ target_sources(TestApp PRIVATE ${IOS_SOURCE})
+ source_group("src\\McOS" FILES ${IOS_SOURCE})
+endif()
+
+set_common_target_properties(TestApp)
+target_include_directories(TestApp
+PUBLIC
+ include
+)
+
+
+if(MSVC)
+ target_compile_options(TestApp PRIVATE -DUNICODE)
+
+ if(PLATFORM_UNIVERSAL_WINDOWS)
+ # Disable w4189: local variable is initialized but not referenced
+ # Disable w4063: case is not a valid value for switch of enum
+ # Consume the windows runtime extensions (/ZW)
+ target_compile_options(TestApp INTERFACE /wd4189 /wd4063 /ZW)
+ endif()
+endif()
+
+if(PLATFORM_WIN32)
+ SET(ENGINE_LIBRARIES
+ GraphicsEngineD3D11-shared
+ GraphicsEngineD3D12-shared
+ GraphicsEngineOpenGL-shared
+ )
+elseif(PLATFORM_ANDROID)
+ SET(ENGINE_LIBRARIES
+ GraphicsEngineOpenGL-shared
+ )
+elseif(PLATFORM_UNIVERSAL_WINDOWS)
+ SET(ENGINE_LIBRARIES
+ GraphicsEngineD3D11-static
+ GraphicsEngineD3D12-static
+ )
+elseif(PLATFORM_LINUX)
+ SET(ENGINE_LIBRARIES
+ GraphicsEngineOpenGL-shared
+ )
+elseif(PLATFORM_MACOS)
+ SET(ENGINE_LIBRARIES
+ GraphicsEngineOpenGL-shared
+ )
+elseif(PLATFORM_IOS)
+ SET(ENGINE_LIBRARIES
+ GraphicsEngineOpenGL-static
+ )
+else()
+ message(FATAL_ERROR "Undefined platform")
+endif()
+
+target_link_libraries(TestApp
+PRIVATE
+ BuildSettings
+PUBLIC
+ NativeAppBase
+ Common
+ GraphicsTools
+ TargetPlatform
+ ${ENGINE_LIBRARIES}
+)
+
+if(PLATFORM_UNIVERSAL_WINDOWS)
+ target_link_libraries(TestApp PRIVATE dxguid.lib)
+elseif(PLATFORM_ANDROID)
+ target_link_libraries(TestApp PRIVATE GLESv3 PUBLIC NativeAppGlue)
+elseif(PLATFORM_LINUX)
+ target_link_libraries(TestApp PRIVATE GL X11)
+elseif(PLATFORM_MACOS OR PLATFORM_IOS)
+
+endif()
+
+source_group("src" FILES ${SOURCE})
+source_group("include" FILES ${INCLUDE})
+
+set_target_properties(TestApp PROPERTIES
+ FOLDER Tests
+)
diff --git a/Tests/TestApp/src/IOS/TestAppIOS.cpp b/Tests/TestApp/src/IOS/TestAppIOS.cpp
new file mode 100644
index 0000000..86edd5d
--- /dev/null
+++ b/Tests/TestApp/src/IOS/TestAppIOS.cpp
@@ -0,0 +1,49 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+
+#include <queue>
+#include "SampleApp.h"
+
+using namespace Diligent;
+
+class TestAppIOS final : public SampleApp
+{
+public:
+ TestAppIOS()
+ {
+ m_DeviceType = DeviceType::OpenGLES;
+ }
+
+ virtual void OnGLContextCreated(void *eaglLayer)override final
+ {
+ InitializeDiligentEngine(eaglLayer);
+ InitializeRenderers();
+ }
+
+private:
+};
+
+NativeAppBase* CreateApplication()
+{
+ return new TestAppIOS;
+}
diff --git a/Tests/TestApp/src/Linux/TestAppLinux.cpp b/Tests/TestApp/src/Linux/TestAppLinux.cpp
new file mode 100644
index 0000000..1d16980
--- /dev/null
+++ b/Tests/TestApp/src/Linux/TestAppLinux.cpp
@@ -0,0 +1,45 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+
+#include "SampleApp.h"
+using namespace Diligent;
+
+class TestAppLinux final : public TestApp
+{
+public:
+ SampleAppLinux()
+ {
+ m_DeviceType = DeviceType::OpenGL;
+ }
+
+ virtual void OnGLContextCreated(Display* display, Window window)override final
+ {
+ InitializeDiligentEngine(display, reinterpret_cast<void*>(static_cast<size_t>(window)));
+ InitializeRenderers();
+ }
+};
+
+NativeAppBase* CreateApplication()
+{
+ return new TestAppLinux;
+}
diff --git a/Tests/TestApp/src/MTResourceCreationTest.cpp b/Tests/TestApp/src/MTResourceCreationTest.cpp
new file mode 100644
index 0000000..f202ba4
--- /dev/null
+++ b/Tests/TestApp/src/MTResourceCreationTest.cpp
@@ -0,0 +1,247 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "MTResourceCreationTest.h"
+#include "Errors.h"
+
+using namespace Diligent;
+
+static const char g_ShaderSource[] =
+"void VSMain(out float4 pos : SV_POSITION) \n"
+"{ \n"
+" pos = float4(0,0,0,0); \n"
+"} \n"
+" \n"
+"void PSMain(out float4 col : SV_TARGET)\n"
+"{ \n"
+" col = float4(0,0,0,0); \n"
+"} \n"
+;
+
+MTResourceCreationTest::MTResourceCreationTest(IRenderDevice *pDevice, IDeviceContext *pContext, Uint32 NumThreads) :
+ m_pDevice(pDevice),
+ m_pContext(pContext)
+{
+ m_NumThreadsCompleted = 0;
+ m_NumBuffersCreated = 0;
+ m_NumTexturesCreated = 0;
+ m_NumPSOCreated = 0;
+
+ auto &DevCaps = m_pDevice->GetDeviceCaps();
+ if (DevCaps.bMultithreadedResourceCreationSupported)
+ {
+ m_Threads.resize(NumThreads);
+ }
+ else
+ {
+ LOG_WARNING_MESSAGE("Multithreaded resource creation is not supported on this device");
+ }
+}
+
+void MTResourceCreationTest::WaitForThreadStart(int VarId)
+{
+ std::unique_lock<std::mutex> lk(m_Mtx);
+ m_CondVar.wait(lk, [&]{return m_bReleaseThread[VarId];});
+}
+
+void MTResourceCreationTest::WaitThreads(int VarId)
+{
+ while((size_t)m_NumThreadsCompleted < m_Threads.size())
+ std::this_thread::yield();
+ m_bReleaseThread[VarId] = false;
+ VERIFY_EXPR(m_NumThreadsCompleted == m_Threads.size());
+}
+
+void MTResourceCreationTest::StartThreads(int VarId)
+{
+ {
+ std::unique_lock<std::mutex> lk(m_Mtx);
+ m_bReleaseThread[VarId] = true;
+ m_NumThreadsCompleted = 0;
+ }
+ m_CondVar.notify_all();
+}
+
+static Uint8 RawBufferData[1024];
+static Uint8 RawTextureData[1024*1024*4];
+
+void MTResourceCreationTest::ThreadWorkerFunc(bool bIsMasterThread)
+{
+ while (!m_bStopThreadsFlagInternal)
+ {
+ if (bIsMasterThread)
+ StartThreads(0);
+ else
+ WaitForThreadStart(0);
+
+ RefCntAutoPtr<IBuffer> pBuffer1, pBuffer2,pBuffer3,pBuffer4;
+ {
+ BufferDesc BuffDesc;
+ BuffDesc.Usage = USAGE_DEFAULT;
+ BuffDesc.BindFlags = BIND_UNIFORM_BUFFER;
+ BuffDesc.Mode = BUFFER_MODE_FORMATTED;
+ BuffDesc.Format.NumComponents = 4;
+ BuffDesc.Format.IsNormalized = False;
+ BuffDesc.Format.ValueType = VT_FLOAT32;
+ BuffDesc.Name = "MT test buffer";
+
+ BuffDesc.uiSizeInBytes = sizeof(RawBufferData);
+
+ BufferData BuffData;
+ BuffData.DataSize = BuffDesc.uiSizeInBytes;
+ BuffData.pData = RawBufferData;
+
+ m_pDevice->CreateBuffer(BuffDesc, BuffData, &pBuffer1);
+
+ BuffDesc.BindFlags = BIND_SHADER_RESOURCE|BIND_UNORDERED_ACCESS;
+ m_pDevice->CreateBuffer(BuffDesc, BuffData, &pBuffer2);
+
+ BuffDesc.BindFlags = BIND_VERTEX_BUFFER|BIND_UNORDERED_ACCESS;
+ m_pDevice->CreateBuffer(BuffDesc, BuffData, &pBuffer3);
+
+ BuffDesc.BindFlags = BIND_INDEX_BUFFER|BIND_UNORDERED_ACCESS;
+ m_pDevice->CreateBuffer(BuffDesc, BuffData, &pBuffer4);
+
+ m_NumBuffersCreated += 4;
+
+ ++m_NumThreadsCompleted;
+ }
+
+ if (bIsMasterThread)
+ {
+ WaitThreads(0);
+
+ // This is the sync point. All threads must reach this point before
+ // master thread can proceed. Othre threads are now waiting for StartThreads(1);
+ // When we set m_bStopThreadsFlagInternal here,
+ // we make sure all threads will exit simultaneously
+ m_bStopThreadsFlagInternal = m_bStopThreadsFlag;
+
+ StartThreads(1);
+ }
+ else
+ WaitForThreadStart(1);
+
+ RefCntAutoPtr<ITexture> pTexture;
+ {
+ TextureDesc TexDesc;
+ TexDesc.BindFlags = BIND_SHADER_RESOURCE | BIND_RENDER_TARGET | BIND_UNORDERED_ACCESS;
+ TexDesc.Type = RESOURCE_DIM_TEX_2D;
+ TexDesc.Width = 1024;
+ TexDesc.Height = 1024;
+ TexDesc.Format = TEX_FORMAT_RGBA8_UNORM;
+ TexDesc.MipLevels = 1;
+
+
+ TextureSubResData SubResData;
+ SubResData.pData = RawTextureData;
+ SubResData.Stride = TexDesc.Width*4;
+
+ TextureData TexData;
+ TexData.NumSubresources = 1;
+ TexData.pSubResources = &SubResData;
+
+ m_pDevice->CreateTexture(TexDesc, TexData, &pTexture);
+ ++m_NumTexturesCreated;
+
+ ++m_NumThreadsCompleted;
+ }
+
+
+ if (bIsMasterThread)
+ {
+ WaitThreads(1);
+ StartThreads(0);
+ }
+ else
+ WaitForThreadStart(0);
+
+
+ RefCntAutoPtr<IShader> pTrivialVS, pTrivialPS;
+ RefCntAutoPtr<IPipelineState> pPSO;
+ {
+ ShaderCreationAttribs Attrs;
+ Attrs.Source = g_ShaderSource;
+ Attrs.EntryPoint = "VSMain";
+ Attrs.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ Attrs.Desc.Name = "TrivialVS";
+ Attrs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
+ m_pDevice->CreateShader(Attrs, &pTrivialVS);
+
+ Attrs.EntryPoint = "PSMain";
+ Attrs.Desc.ShaderType = SHADER_TYPE_PIXEL;
+ Attrs.Desc.Name = "TrivialPS";
+ m_pDevice->CreateShader(Attrs, &pTrivialPS);
+
+ PipelineStateDesc PSODesc;
+ PSODesc.GraphicsPipeline.pVS = pTrivialVS;
+ PSODesc.GraphicsPipeline.pPS = pTrivialPS;
+ PSODesc.GraphicsPipeline.PrimitiveTopologyType = PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
+ PSODesc.GraphicsPipeline.NumRenderTargets = 1;
+ PSODesc.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM;
+ PSODesc.GraphicsPipeline.DSVFormat = TEX_FORMAT_D32_FLOAT;
+
+ m_pDevice->CreatePipelineState(PSODesc, &pPSO);
+ ++m_NumPSOCreated;
+
+ ++m_NumThreadsCompleted;
+ }
+
+ if (bIsMasterThread)
+ {
+ WaitThreads(0);
+ StartThreads(1);
+ }
+ else
+ WaitForThreadStart(1);
+
+
+ {
+
+ ++m_NumThreadsCompleted;
+ }
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+
+ if (bIsMasterThread)
+ WaitThreads(1);
+ }
+}
+
+void MTResourceCreationTest::StartThreads()
+{
+ for(size_t t=0; t < m_Threads.size(); ++t)
+ m_Threads[t] = std::thread(&MTResourceCreationTest::ThreadWorkerFunc, this, t == 0);
+}
+
+void MTResourceCreationTest::StopThreads()
+{
+ m_bStopThreadsFlag = true;
+ for(auto &t : m_Threads)
+ t.join();
+ LOG_INFO_MESSAGE("MTResourceCreationTest: Buffers created: ", m_NumBuffersCreated, " Textures created: ", m_NumTexturesCreated, " PSO Created: ", m_NumPSOCreated);
+}
diff --git a/Tests/TestApp/src/MacOS/TestAppMacOS.cpp b/Tests/TestApp/src/MacOS/TestAppMacOS.cpp
new file mode 100644
index 0000000..60e5a86
--- /dev/null
+++ b/Tests/TestApp/src/MacOS/TestAppMacOS.cpp
@@ -0,0 +1,47 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+
+#include <queue>
+#include "SampleApp.h"
+
+using namespace Diligent;
+
+class TestAppMacOS final : public SampleApp
+{
+public:
+ TestAppMacOS()
+ {
+ m_DeviceType = DeviceType::OpenGL;
+ }
+
+ virtual void OnGLContextCreated()override final
+ {
+ InitializeDiligentEngine(nullptr);
+ InitializeRenderers();
+ }
+};
+
+NativeAppBase* CreateApplication()
+{
+ return new TestAppMacOS;
+}
diff --git a/Tests/TestApp/src/MathLibTest.cpp b/Tests/TestApp/src/MathLibTest.cpp
new file mode 100644
index 0000000..78b1560
--- /dev/null
+++ b/Tests/TestApp/src/MathLibTest.cpp
@@ -0,0 +1,503 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "BasicMath.h"
+#include "DebugUtilities.h"
+
+using namespace Diligent;
+
+class MathLibTest
+{
+public:
+ MathLibTest()
+ {
+ // Ctor
+ {
+ float2 f2( 1, 2 );
+ VERIFY_EXPR( f2.x == 1 && f2.y == 2 );
+ VERIFY_EXPR( f2.x == f2[0] && f2.y == f2[1] );
+ }
+
+ {
+ float3 f3( 1, 2, 3 );
+ VERIFY_EXPR( f3.x == 1 && f3.y == 2 && f3.z == 3 );
+ VERIFY_EXPR( f3.x == f3[0] && f3.y == f3[1] && f3.z == f3[2] );
+ }
+
+ {
+ float4 f4( 1, 2, 3, 4 );
+ VERIFY_EXPR( f4.x == 1 && f4.y == 2 && f4.z == 3 && f4.w == 4 );
+ VERIFY_EXPR( f4.x == f4[0] && f4.y == f4[1] && f4.z == f4[2] && f4.w == f4[3] );
+ }
+
+
+ // a - b
+ {
+ auto v = float2( 5, 3 ) - float2( 1, 2 );
+ VERIFY_EXPR( v.x == 4 && v.y == 1 );
+ }
+
+ {
+ auto v = float3( 5, 3, 20 ) - float3( 1, 2, 10 );
+ VERIFY_EXPR( v.x == 4 && v.y == 1 && v.z == 10);
+ }
+
+ {
+ auto v = float4( 5, 3, 20, 200 ) - float4( 1, 2, 10, 100 );
+ VERIFY_EXPR( v.x == 4 && v.y == 1 && v.z == 10 && v.w == 100);
+ }
+
+ // a -= b
+ {
+ auto v = float2( 5, 3 );
+ v -= float2( 1, 2 );
+ VERIFY_EXPR( v.x == 4 && v.y == 1 );
+ }
+
+ {
+ auto v = float3( 5, 3, 20 );
+ v -= float3( 1, 2, 10 );
+ VERIFY_EXPR( v.x == 4 && v.y == 1 && v.z == 10);
+ }
+
+ {
+ auto v = float4( 5, 3, 20, 200 );
+ v -= float4( 1, 2, 10, 100 );
+ VERIFY_EXPR( v.x == 4 && v.y == 1 && v.z == 10 && v.w == 100);
+ }
+
+ // -a
+ {
+ auto v = -float2( 1, 2 );
+ VERIFY_EXPR( v.x == -1 && v.y == -2 );
+ }
+
+ {
+ auto v = -float3( 1, 2, 3 );
+ VERIFY_EXPR( v.x == -1 && v.y == -2 && v.z == -3 );
+ }
+
+ {
+ auto v = -float4( 1, 2, 3, 4 );
+ VERIFY_EXPR( v.x == -1 && v.y == -2 && v.z == -3 && v.w == -4 );
+ }
+
+
+ // a + b
+ {
+ auto v = float2( 5, 3 ) + float2( 1, 2 );
+ VERIFY_EXPR( v.x == 6 && v.y == 5 );
+ }
+
+ {
+ auto v = float3( 5, 3, 20 ) + float3( 1, 2, 10 );
+ VERIFY_EXPR( v.x == 6 && v.y == 5 && v.z == 30);
+ }
+
+ {
+ auto v = float4( 5, 3, 20, 200 ) + float4( 1, 2, 10, 100 );
+ VERIFY_EXPR( v.x == 6 && v.y == 5 && v.z == 30 && v.w == 300);
+ }
+
+ // a += b
+ {
+ auto v = float2( 5, 3 );
+ v += float2( 1, 2 );
+ VERIFY_EXPR( v.x == 6 && v.y == 5 );
+ }
+
+ {
+ auto v = float3( 5, 3, 20 );
+ v+=float3( 1, 2, 10 );
+ VERIFY_EXPR( v.x == 6 && v.y == 5 && v.z == 30);
+ }
+
+ {
+ auto v = float4( 5, 3, 20, 200 );
+ v+=float4( 1, 2, 10, 100 );
+ VERIFY_EXPR( v.x == 6 && v.y == 5 && v.z == 30 && v.w == 300);
+ }
+
+ // a * b
+ {
+ auto v = float2( 5, 3 ) * float2( 1, 2 );
+ VERIFY_EXPR( v.x == 5 && v.y == 6 );
+ }
+
+ {
+ auto v = float3( 5, 3, 20 ) * float3( 1, 2, 3 );
+ VERIFY_EXPR( v.x == 5 && v.y == 6 && v.z == 60);
+ }
+
+ {
+ auto v = float4( 5, 3, 20, 200 ) * float4( 1, 2, 3, 4 );
+ VERIFY_EXPR( v.x == 5 && v.y == 6 && v.z == 60 && v.w == 800);
+ }
+
+ // a *= b
+ {
+ auto v = float2( 5, 3 );
+ v*=float2( 1, 2 );
+ VERIFY_EXPR( v.x == 5 && v.y == 6 );
+ }
+
+ {
+ auto v = float3( 5, 3, 20 );
+ v*=float3( 1, 2, 3 );
+ VERIFY_EXPR( v.x == 5 && v.y == 6 && v.z == 60);
+ }
+
+ {
+ auto v = float4( 5, 3, 20, 200 );
+ v*=float4( 1, 2, 3, 4 );
+ VERIFY_EXPR( v.x == 5 && v.y == 6 && v.z == 60 && v.w == 800);
+ }
+
+ // a * s
+ {
+ auto v = float2( 5, 3 )*2;
+ VERIFY_EXPR( v.x == 10 && v.y == 6 );
+ }
+
+ {
+ auto v = float3( 5, 3, 20 )*2;
+ VERIFY_EXPR( v.x == 10 && v.y == 6 && v.z == 40);
+ }
+
+ {
+ auto v = float4( 5, 3, 20, 200 ) * 2;
+ VERIFY_EXPR( v.x == 10 && v.y == 6 && v.z == 40 && v.w == 400);
+ }
+
+ // a *= s
+ {
+ auto v = float2( 5, 3 );
+ v*=2;
+ VERIFY_EXPR( v.x == 10 && v.y == 6 );
+ }
+
+ {
+ auto v = float3( 5, 3, 20 );
+ v*=2;
+ VERIFY_EXPR( v.x == 10 && v.y == 6 && v.z == 40);
+ }
+
+ {
+ auto v = float4( 5, 3, 20, 200 );
+ v*=2;
+ VERIFY_EXPR( v.x == 10 && v.y == 6 && v.z == 40 && v.w == 400);
+ }
+
+ // s * a
+ {
+ auto v = 2.f * float2( 5, 3 );
+ VERIFY_EXPR( v.x == 10 && v.y == 6 );
+ }
+
+ {
+ auto v = 2.f * float3( 5, 3, 20 );
+ VERIFY_EXPR( v.x == 10 && v.y == 6 && v.z == 40);
+ }
+
+ {
+ auto v = 2.f * float4( 5, 3, 20, 200 );
+ VERIFY_EXPR( v.x == 10 && v.y == 6 && v.z == 40 && v.w == 400);
+ }
+
+ // a / s
+ {
+ auto v = float2( 10, 6 )/2;
+ VERIFY_EXPR( v.x == 5 && v.y == 3 );
+ }
+
+ {
+ auto v = float3( 10, 6, 40 )/2;
+ VERIFY_EXPR( v.x == 5 && v.y == 3 && v.z == 20);
+ }
+
+ {
+ auto v = float4( 10, 6, 40, 400 ) / 2;
+ VERIFY_EXPR( v.x == 5 && v.y == 3 && v.z == 20 && v.w == 200);
+ }
+
+
+ // a / b
+ {
+ auto v = float2( 6, 4 ) / float2( 1, 2 );
+ VERIFY_EXPR( v.x == 6 && v.y == 2 );
+ }
+
+ {
+ auto v = float3( 6, 3, 20 ) / float3( 3, 1, 5 );
+ VERIFY_EXPR( v.x == 2 && v.y == 3 && v.z == 4);
+ }
+
+ {
+ auto v = float4( 6, 3, 20, 200 ) / float4( 3, 1, 5, 40 );
+ VERIFY_EXPR( v.x == 2 && v.y == 3 && v.z == 4 && v.w == 5);
+ }
+
+ // a /= b
+ {
+ auto v = float2( 6, 4 );
+ v/=float2( 1, 2 );
+ VERIFY_EXPR( v.x == 6 && v.y == 2 );
+ }
+
+ {
+ auto v = float3( 6, 3, 20 );
+ v/=float3( 3, 1, 5 );
+ VERIFY_EXPR( v.x == 2 && v.y == 3 && v.z == 4);
+ }
+
+ {
+ auto v = float4( 6, 3, 20, 200 );
+ v/=float4( 3, 1, 5, 40 );
+ VERIFY_EXPR( v.x == 2 && v.y == 3 && v.z == 4 && v.w == 5);
+ }
+
+ // a /= s
+ {
+ auto v = float2( 6, 4 );
+ v/=2;
+ VERIFY_EXPR( v.x == 3 && v.y == 2 );
+ }
+
+ {
+ auto v = float3( 4, 6, 20 );
+ v/=2;
+ VERIFY_EXPR( v.x == 2 && v.y == 3 && v.z == 10);
+ }
+
+ {
+ auto v = float4( 4, 6, 20, 200 );
+ v/=2;
+ VERIFY_EXPR( v.x == 2 && v.y == 3 && v.z == 10 && v.w == 100);
+ }
+
+ // max
+ {
+ auto v = std::max( float2( 6, 4 ), float2( 1, 40 ) );
+ VERIFY_EXPR( v.x == 6 && v.y == 40 );
+ }
+
+ {
+ auto v = std::max( float3( 4, 6, 20 ), float3( 40, 3, 23 ) );
+ VERIFY_EXPR( v.x == 40 && v.y == 6 && v.z == 23);
+ }
+
+ {
+ auto v = std::max( float4( 4, 6, 20, 100 ), float4( 40, 3, 23, 50 ) );
+ VERIFY_EXPR( v.x == 40 && v.y == 6 && v.z == 23 && v.w == 100);
+ }
+
+ // min
+ {
+ auto v = std::min( float2( 6, 4 ), float2( 1, 40 ) );
+ VERIFY_EXPR( v.x == 1 && v.y == 4 );
+ }
+
+ {
+ auto v = std::min( float3( 4, 6, 20 ), float3( 40, 3, 23 ) );
+ VERIFY_EXPR( v.x == 4 && v.y == 3 && v.z == 20);
+ }
+
+ {
+ auto v = std::min( float4( 4, 6, 20, 100 ), float4( 40, 3, 23, 50 ) );
+ VERIFY_EXPR( v.x == 4 && v.y == 3 && v.z == 20 && v.w == 50);
+ }
+
+
+ // a == b
+ {
+ VERIFY_EXPR( float2(1,2) == float2(1,2) );
+ VERIFY_EXPR( float3(1,2,3) == float3(1,2,3) );
+ VERIFY_EXPR( float4(1,2,3,4) == float4(1,2,3,4) );
+ }
+
+ // a != b
+ {
+ VERIFY_EXPR( float2(1,2) != float2(1,9) && float2(9,2) != float2(1,2) );
+ VERIFY_EXPR( float3(1,2,3) != float3(9,2,3) && float3(1,2,3) != float3(1,9,3) && float3(1,2,3) != float3(1,2,9) );
+ VERIFY_EXPR( float4(1,2,3,4) != float4(9,2,3,4) && float4(1,2,3,4) != float4(1,9,3,4) && float4(1,2,3,4) != float4(1,2,9,4) && float4(1,2,3,4) != float4(1,2,3,9) );
+ }
+
+ // a < b
+ {
+ VERIFY_EXPR( float2(1,5) < float2(3,5) == float2(1,0) );
+ VERIFY_EXPR( float2(3,1) < float2(3,4) == float2(0,1) );
+ VERIFY_EXPR( float3(1,5,10) < float3(3,5,20) == float3(1,0,1) );
+ VERIFY_EXPR( float3(3,1,2) < float3(3,4,2) == float3(0,1,0) );
+ VERIFY_EXPR( float4(1,4,10,50) < float4(3,4,20, 50) == float4(1,0,1,0) );
+ VERIFY_EXPR( float4(3,1,2,30) < float4(3,4,2, 70) == float4(0,1,0,1) );
+ }
+
+ // a <= b
+ {
+ VERIFY_EXPR( float2(1,5) <= float2(1,4) == float2(1,0) );
+ VERIFY_EXPR( float2(5,2) <= float2(3,2) == float2(0,1) );
+ VERIFY_EXPR( float3(3,5,10) <= float3(3,4,10) == float3(1,0,1) );
+ VERIFY_EXPR( float3(5,4,2) <= float3(3,4,0) == float3(0,1,0) );
+ VERIFY_EXPR( float4(3,5,20,100) <= float4(3,4,20, 50) == float4(1,0,1,0) );
+ VERIFY_EXPR( float4(5,4,2,70) <= float4(3,4,0, 70) == float4(0,1,0,1) );
+ }
+
+ // a >= b
+ {
+ VERIFY_EXPR( float2(1,5) >= float2(3,5) == float2(0,1) );
+ VERIFY_EXPR( float2(3,1) >= float2(3,4) == float2(1,0) );
+ VERIFY_EXPR( float3(1,5,10) >= float3(3,5,20) == float3(0,1,0) );
+ VERIFY_EXPR( float3(3,1,2) >= float3(3,4,2) == float3(1,0,1) );
+ VERIFY_EXPR( float4(1,4,10,50) >= float4(3,4,20, 50) == float4(0,1,0,1) );
+ VERIFY_EXPR( float4(3,1,2,30) >= float4(3,4,2, 70) == float4(1,0,1,0) );
+ }
+
+ // a > b
+ {
+ VERIFY_EXPR( float2(1,5) > float2(1,4) == float2(0,1) );
+ VERIFY_EXPR( float2(5,2) > float2(3,2) == float2(1,0) );
+ VERIFY_EXPR( float3(3,5,10) > float3(3,4,10) == float3(0,1,0) );
+ VERIFY_EXPR( float3(5,4,2) > float3(3,4,0) == float3(1,0,1) );
+ VERIFY_EXPR( float4(3,5,20,100) > float4(3,4,20, 50) == float4(0,1,0,1) );
+ VERIFY_EXPR( float4(5,4,2,70) > float4(3,4,0, 70) == float4(1,0,1,0) );
+ }
+
+ // abs
+ {
+ VERIFY_EXPR( abs(float2(-1,-5)) == float2( 1, 5) );
+ VERIFY_EXPR( abs(float2( 1, 5)) == float2( 1, 5) );
+
+ VERIFY_EXPR( abs(float3(-1,-5, -10)) == float3( 1, 5, 10) );
+ VERIFY_EXPR( abs(float3( 1, 5, 10)) == float3( 1, 5, 10) );
+
+ VERIFY_EXPR( abs(float4(-1,-5, -10, -100)) == float4( 1, 5, 10, 100) );
+ VERIFY_EXPR( abs(float4( 1, 5, 10, 100)) == float4( 1, 5, 10, 100) );
+ }
+
+ // dot
+ {
+ VERIFY_EXPR( dot( float2( 1, 2 ), float2( 1, 2 ) ) == 5 );
+ VERIFY_EXPR( dot( float3( 1, 2, 3 ), float3( 1, 2, 3 ) ) == 14 );
+ VERIFY_EXPR( dot( float4( 1, 2, 3, 4 ), float4( 1, 2, 3, 4 ) ) == 30 );
+ }
+
+ // length
+ {
+ auto l = length( float2(3,4) );
+ VERIFY_EXPR( l >= 5.f - 1e-6f && l <= 5.f + 1e+6f );
+ }
+
+ // Matrix 3x3
+ {
+ float3x3 m1( 1, 2, 3,
+ 5, 6, 7,
+ 9, 10, 11),
+ m2( 1, 2, 3,
+ 5, 6, 7,
+ 9, 10, 11);
+ VERIFY_EXPR(m1._11 == 1 && m1._12 == 2 && m1._13 == 3 &&
+ m1._21 == 5 && m1._22 == 6 && m1._23 == 7 &&
+ m1._31 == 9 && m1._32 == 10 && m1._33 == 11 );
+ VERIFY_EXPR(m1[0][0] == 1 && m1[0][1] == 2 && m1[0][2] == 3 &&
+ m1[1][0] == 5 && m1[1][1] == 6 && m1[1][2] == 7 &&
+ m1[2][0] == 9 && m1[2][1] == 10 && m1[2][2] == 11 );
+
+ VERIFY_EXPR( m1 == m2 );
+ auto t = transposeMatrix( transposeMatrix( m1 ) );
+ VERIFY_EXPR( t == m1 );
+ }
+
+ // Matrix 4x4
+ {
+ float4x4 m1( 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16),
+ m2( 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16) ;
+ VERIFY_EXPR(m1._11 == 1 && m1._12 == 2 && m1._13 == 3 && m1._14 == 4 &&
+ m1._21 == 5 && m1._22 == 6 && m1._23 == 7 && m1._24 == 8 &&
+ m1._31 == 9 && m1._32 == 10 && m1._33 == 11 && m1._34 == 12 &&
+ m1._41 == 13 && m1._42 == 14 && m1._43 == 15 && m1._44 == 16 );
+ VERIFY_EXPR(m1[0][0] == 1 && m1[0][1] == 2 && m1[0][2] == 3 && m1[0][3] == 4 &&
+ m1[1][0] == 5 && m1[1][1] == 6 && m1[1][2] == 7 && m1[1][3] == 8 &&
+ m1[2][0] == 9 && m1[2][1] == 10 && m1[2][2] == 11 && m1[2][3] == 12 &&
+ m1[3][0] == 13 && m1[3][1] == 14 && m1[3][2] == 15 && m1[3][3] == 16 );
+
+ VERIFY_EXPR( m1 == m2 );
+ auto t = transposeMatrix( transposeMatrix( m1 ) );
+ VERIFY_EXPR( t == m1 );
+ }
+
+ // Inverse
+ {
+ float4x4 m( 7, 8, 3, 6,
+ 5, 1, 4, 9,
+ 5, 11, 7, 2,
+ 13, 4, 19, 8);
+ auto inv = inverseMatrix( m );
+ auto identity = m * inv;
+ for( int j = 0; j < 4; ++j)
+ for( int i = 0; i < 4; ++i )
+ {
+ float ref = i == j ? 1.f : 0.f;
+ auto val = identity[i][j];
+ VERIFY_EXPR( fabs( val - ref ) < 1e-6f );
+ }
+ }
+
+ // Determinant
+ {
+ float4x4 m1( 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16);
+ auto det = determinant(m1);
+ VERIFY_EXPR( det == 0 );
+ }
+
+ {
+ std::hash<float2>()(float2(1.0, 2.0));
+ std::hash<float3>()(float3(1.0, 2.0, 3.0));
+ std::hash<float4>()(float4(1.0, 2.0, 3.0, 5.0));
+ float4x4 m1( 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16);
+ std::hash<float4x4>()(m1);
+
+ float3x3 m2( 1, 2, 3,
+ 5, 6, 7,
+ 9, 10, 11);
+ std::hash<float3x3>()(m2);
+ }
+ }
+};
+
+static MathLibTest MathLibTest; \ No newline at end of file
diff --git a/Tests/TestApp/src/RenderScriptTest.cpp b/Tests/TestApp/src/RenderScriptTest.cpp
new file mode 100644
index 0000000..abe65e7
--- /dev/null
+++ b/Tests/TestApp/src/RenderScriptTest.cpp
@@ -0,0 +1,424 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "RenderScriptTest.h"
+#include "FileSystem.h"
+#include "Errors.h"
+#include "ScriptParser.h"
+#include "ConvenienceFunctions.h"
+
+using namespace Diligent;
+
+RenderScriptTest::RenderScriptTest( IRenderDevice *pRenderDevice, IDeviceContext *pContext )
+{
+ RefCntAutoPtr<ITexture> pTestGlobalTexture;
+ {
+ TextureDesc TexDesc;
+ TexDesc.Type = RESOURCE_DIM_TEX_2D;
+ TexDesc.Name = "Test Global Texture 2D";
+ TexDesc.Width = 1024;
+ TexDesc.Height = 512;
+ TexDesc.MipLevels = 1;
+ TexDesc.Format = TEX_FORMAT_RGBA8_UNORM;
+ TexDesc.Usage = USAGE_DYNAMIC;
+ TexDesc.BindFlags = BIND_SHADER_RESOURCE;
+ TexDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ pRenderDevice->CreateTexture( TexDesc, TextureData(), &pTestGlobalTexture );
+ }
+
+ auto pScript = CreateRenderScriptFromFile( "LuaTest.lua", pRenderDevice, pContext, [&]( Diligent::ScriptParser *pScriptParser )
+ {
+ pScriptParser->SetGlobalVariable( "TestGlobalBool", True );
+ pScriptParser->SetGlobalVariable( "TestGlobalInt", (Int32)19 );
+ pScriptParser->SetGlobalVariable( "TestGlobalFloat", (Float32)139.25 );
+ pScriptParser->SetGlobalVariable( "TestGlobalString", "Test Global String" );
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.Name = "TestGlobalBuff";
+ BuffDesc.uiSizeInBytes = 256;
+ BuffDesc.BindFlags = BIND_UNIFORM_BUFFER;
+ BuffDesc.Usage = USAGE_DYNAMIC;
+ BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ RefCntAutoPtr<IBuffer> pBuffer;
+ pRenderDevice->CreateBuffer( BuffDesc, Diligent::BufferData(), &pBuffer );
+ pScriptParser->SetGlobalVariable( "TestGlobalBuffer", pBuffer );
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.Name = "TestGlobalBuff2";
+ BuffDesc.uiSizeInBytes = 64;
+ BuffDesc.BindFlags = BIND_VERTEX_BUFFER | BIND_UNORDERED_ACCESS;
+ BuffDesc.Usage = USAGE_DEFAULT;
+ BuffDesc.Format.ValueType = VT_UINT16;
+ BuffDesc.Format.NumComponents = 4;
+ BuffDesc.Format.IsNormalized = true;
+ BuffDesc.Mode = BUFFER_MODE_FORMATTED;
+ RefCntAutoPtr<IBuffer> pBuffer;
+ pRenderDevice->CreateBuffer( BuffDesc, Diligent::BufferData(), &pBuffer );
+ pScriptParser->SetGlobalVariable( "TestGlobalBufferWithUAV", pBuffer );
+
+ auto *pUAV = pBuffer->GetDefaultView( BUFFER_VIEW_UNORDERED_ACCESS );
+ pScriptParser->SetGlobalVariable( "TestGlobalBuffer2UAV", pUAV );
+ }
+
+ {
+ SamplerDesc SamplerDesc;
+ SamplerDesc.Name = "Test Sampler";
+ SamplerDesc.MinFilter = FILTER_TYPE_COMPARISON_POINT;
+ SamplerDesc.MagFilter = FILTER_TYPE_COMPARISON_LINEAR;
+ SamplerDesc.MipFilter = FILTER_TYPE_COMPARISON_LINEAR;
+ SamplerDesc.AddressU = TEXTURE_ADDRESS_WRAP;
+ SamplerDesc.AddressV = TEXTURE_ADDRESS_MIRROR;
+ SamplerDesc.AddressW = TEXTURE_ADDRESS_CLAMP;
+ SamplerDesc.MipLODBias = 4;
+ SamplerDesc.MinLOD = 1.5f;
+ SamplerDesc.MaxLOD = 4;
+ SamplerDesc.MaxAnisotropy = 2;
+ SamplerDesc.ComparisonFunc = COMPARISON_FUNC_LESS;
+ SamplerDesc.BorderColor[0] = 1.5f;
+ SamplerDesc.BorderColor[1] = 2.25f;
+ SamplerDesc.BorderColor[2] = 3.125f;
+ SamplerDesc.BorderColor[3] = 4.0625f;
+ RefCntAutoPtr<ISampler> pSampler;
+ pRenderDevice->CreateSampler( SamplerDesc, &pSampler );
+ pScriptParser->SetGlobalVariable( "TestGlobalSampler", pSampler );
+ }
+
+ {
+ pScriptParser->SetGlobalVariable( "TestGlobalTexture", pTestGlobalTexture );
+ }
+
+ {
+ DrawAttribs GlobalDrawAttribs;
+ GlobalDrawAttribs.Topology = PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ GlobalDrawAttribs.NumVertices = 123;
+ GlobalDrawAttribs.IndexType = VT_UINT16;
+ GlobalDrawAttribs.IsIndexed = True;
+ GlobalDrawAttribs.NumInstances = 19;
+ GlobalDrawAttribs.IsIndirect = True;
+ GlobalDrawAttribs.BaseVertex = 97;
+ GlobalDrawAttribs.IndirectDrawArgsOffset = 120;
+ GlobalDrawAttribs.StartVertexLocation = 98;
+ pScriptParser->SetGlobalVariable( "TestGlobalDrawAttribs", GlobalDrawAttribs );
+ }
+
+ auto DevType = pRenderDevice->GetDeviceCaps().DevType;
+ if( DevType == DeviceType::D3D11 || DevType == DeviceType::D3D12 )
+ {
+ TextureViewDesc TestTexViewDesc;
+ TestTexViewDesc.Name = "TestTextureSRV2";
+ TestTexViewDesc.ViewType = TEXTURE_VIEW_SHADER_RESOURCE;
+ TestTexViewDesc.TextureDim = RESOURCE_DIM_TEX_2D;
+ TestTexViewDesc.Format = TEX_FORMAT_RGBA8_UNORM;
+ RefCntAutoPtr<ITextureView> pTestTextureView;
+ pTestGlobalTexture->CreateView( TestTexViewDesc, &pTestTextureView );
+ pScriptParser->SetGlobalVariable( "TestGlobalTextureView", pTestTextureView );
+ }
+
+ {
+ ResourceMappingEntry Entries[] = {
+ { "TestGlobalTextureSRV", pTestGlobalTexture->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)},
+ ResourceMappingEntry()
+ };
+ ResourceMappingDesc ResMappingDesc;
+ ResMappingDesc.pEntries= Entries;
+ RefCntAutoPtr<IResourceMapping> pResMapping;
+ pRenderDevice->CreateResourceMapping( ResMappingDesc, &pResMapping );
+ pScriptParser->SetGlobalVariable( "TestGlobalResourceMapping", pResMapping );
+ }
+ } );
+
+ {
+ RefCntAutoPtr<ISampler> pTestSampler;
+ pScript->GetSamplerByName( "TestSampler", &pTestSampler );
+ const auto &SamplerDesc = pTestSampler->GetDesc();
+ assert( strcmp(SamplerDesc.Name, "Test Sampler") == 0 );
+ assert( SamplerDesc.MinFilter == FILTER_TYPE_POINT );
+ assert( SamplerDesc.MagFilter == FILTER_TYPE_LINEAR );
+ assert( SamplerDesc.MipFilter == FILTER_TYPE_POINT );
+ assert( SamplerDesc.AddressU == TEXTURE_ADDRESS_WRAP );
+ assert( SamplerDesc.AddressV == TEXTURE_ADDRESS_MIRROR );
+ assert( SamplerDesc.AddressW == TEXTURE_ADDRESS_CLAMP );
+ assert( SamplerDesc.MipLODBias == 2 );
+ assert( SamplerDesc.MinLOD == 0.5f );
+ assert( SamplerDesc.MaxLOD == 10 );
+ assert( SamplerDesc.MaxAnisotropy == 6 );
+ assert( SamplerDesc.ComparisonFunc == COMPARISON_FUNC_GREATER_EQUAL );
+ assert( SamplerDesc.BorderColor[0] == 0.5f );
+ assert( SamplerDesc.BorderColor[1] == 0.25f );
+ assert( SamplerDesc.BorderColor[2] == 0.125f );
+ assert( SamplerDesc.BorderColor[3] == 0.0625f );
+ }
+
+ {
+ RefCntAutoPtr<ISampler> pTestSampler3;
+ pScript->GetSamplerByName( "TestSampler3", &pTestSampler3 );
+ const auto &SamplerDesc = pTestSampler3->GetDesc();
+ assert( SamplerDesc.BorderColor[0] == 0.5f * 2.f);
+ assert( SamplerDesc.BorderColor[1] == 0.25f * 2.f );
+ assert( SamplerDesc.BorderColor[2] == 0.125f * 2.f );
+ assert( SamplerDesc.BorderColor[3] == 0.0625f * 2.f );
+ }
+
+ {
+ RefCntAutoPtr<ISampler> pTestSampler2;
+ pScript->GetSamplerByName( "TestSampler2", &pTestSampler2 );
+ const auto &SamplerDesc = pTestSampler2->GetDesc();
+ assert( strcmp(SamplerDesc.Name, "Test Sampler") == 0);
+ assert( SamplerDesc.MinFilter == FILTER_TYPE_POINT );
+ assert( SamplerDesc.MagFilter == FILTER_TYPE_LINEAR );
+ assert( SamplerDesc.MipFilter == FILTER_TYPE_POINT );
+ assert( SamplerDesc.AddressU == TEXTURE_ADDRESS_WRAP );
+ assert( SamplerDesc.AddressV == TEXTURE_ADDRESS_MIRROR );
+ assert( SamplerDesc.AddressW == TEXTURE_ADDRESS_CLAMP );
+ assert( SamplerDesc.MipLODBias == 2 );
+ assert( SamplerDesc.MinLOD == 0.5f );
+ assert( SamplerDesc.MaxLOD == 10 );
+ assert( SamplerDesc.MaxAnisotropy == 6 );
+ assert( SamplerDesc.ComparisonFunc == COMPARISON_FUNC_GREATER_EQUAL );
+ assert( SamplerDesc.BorderColor[0] == 0.5f );
+ assert( SamplerDesc.BorderColor[1] == 0.25f );
+ assert( SamplerDesc.BorderColor[2] == 0.125f );
+ assert( SamplerDesc.BorderColor[3] == 0.0625f );
+ }
+
+
+ {
+ RefCntAutoPtr<ISampler> pTestSampler4;
+ pScript->GetSamplerByName( "TestSampler4", &pTestSampler4 );
+ const auto &SamDesc = pTestSampler4->GetDesc();
+ assert( strcmp(SamDesc.Name, "") == 0 );
+ assert( SamDesc.MinFilter == SamplerDesc().MinFilter );
+ assert( SamDesc.MagFilter == SamplerDesc().MagFilter );
+ assert( SamDesc.MipFilter == SamplerDesc().MipFilter );
+ assert( SamDesc.AddressU == SamplerDesc().AddressU );
+ assert( SamDesc.AddressV == SamplerDesc().AddressV );
+ assert( SamDesc.AddressW == SamplerDesc().AddressW );
+ assert( SamDesc.MipLODBias == SamplerDesc().MipLODBias );
+ assert( SamDesc.MinLOD == SamplerDesc().MinLOD );
+ assert( SamDesc.MaxLOD == SamplerDesc().MaxLOD );
+ assert( SamDesc.MaxAnisotropy == SamplerDesc().MaxAnisotropy );
+ assert( SamDesc.ComparisonFunc == SamplerDesc().ComparisonFunc );
+ assert( SamDesc.BorderColor[0] == SamplerDesc().BorderColor[0] );
+ assert( SamDesc.BorderColor[1] == SamplerDesc().BorderColor[1] );
+ assert( SamDesc.BorderColor[2] == SamplerDesc().BorderColor[2] );
+ assert( SamDesc.BorderColor[3] == SamplerDesc().BorderColor[3] );
+ }
+
+ for( int iVertLayout = 0; iVertLayout < 3; ++iVertLayout )
+ {
+ std::stringstream ss1;
+ ss1 << "TestVertexLayoutPSO";
+ if( iVertLayout > 0 )
+ {
+ ss1 << (iVertLayout + 1);
+ }
+ String VariableName = ss1.str();
+
+ RefCntAutoPtr<IPipelineState> pTestPSO;
+ pScript->GetPipelineStateByName( VariableName.c_str(), &pTestPSO );
+ const auto &Desc = pTestPSO->GetDesc().GraphicsPipeline.InputLayout;
+ assert( Desc.NumElements == 3 );
+ assert( Desc.LayoutElements[0].InputIndex == 0 );
+ assert( Desc.LayoutElements[0].BufferSlot == 0 );
+ assert( Desc.LayoutElements[0].NumComponents == 3 );
+ assert( Desc.LayoutElements[0].ValueType == VT_FLOAT32 );
+ assert( Desc.LayoutElements[0].IsNormalized == false );
+
+ assert( Desc.LayoutElements[1].InputIndex == 1 );
+ assert( Desc.LayoutElements[1].BufferSlot == 1 );
+ assert( Desc.LayoutElements[1].NumComponents == 4 );
+ assert( Desc.LayoutElements[1].ValueType == VT_UINT8 );
+ assert( Desc.LayoutElements[1].IsNormalized == true );
+
+ assert( Desc.LayoutElements[2].InputIndex == 2 );
+ assert( Desc.LayoutElements[2].BufferSlot == 2 );
+ assert( Desc.LayoutElements[2].NumComponents == 2 );
+ assert( Desc.LayoutElements[2].ValueType == VT_FLOAT32 );
+ assert( Desc.LayoutElements[2].IsNormalized == false );
+ assert( Desc.LayoutElements[2].Frequency == LayoutElement::FREQUENCY_PER_INSTANCE );
+ assert( Desc.LayoutElements[2].InstanceDataStepRate == 1 );
+ }
+
+ {
+ RefCntAutoPtr<IShader> pTestVS;
+ pScript->GetShaderByName( "TestVS", &pTestVS );
+ const auto &Desc = pTestVS->GetDesc();
+ assert( strcmp(Desc.Name, "TestVS") == 0 );
+ assert( Desc.ShaderType == SHADER_TYPE_VERTEX );
+ }
+
+ {
+ RefCntAutoPtr<IShader> pTestPS;
+ pScript->GetShaderByName( "TestPS", &pTestPS );
+ const auto &Desc = pTestPS->GetDesc();
+ assert( strcmp(Desc.Name, "TestPS") == 0 );
+ assert( Desc.ShaderType == SHADER_TYPE_PIXEL );
+ }
+
+ {
+ RefCntAutoPtr<IShader> pTestPS2;
+ pScript->GetShaderByName( "TestPS2", &pTestPS2 );
+ const auto &Desc = pTestPS2->GetDesc();
+ assert( strcmp(Desc.Name, "TestPS2") == 0 );
+ assert( Desc.ShaderType == SHADER_TYPE_PIXEL );
+ }
+
+ Int32 MagicNumber1 = 123;
+ float MagicNumber2 = 345.5f;
+ String MagicString = "Magic String";
+ pScript->Run( "TestRenderScriptParams", True, MagicNumber1, MagicNumber2, False, MagicString );
+
+ {
+ RefCntAutoPtr<ISampler> pTestSampler;
+ pScript->GetSamplerByName( "TestSampler", &pTestSampler );
+ pScript->Run( "TestSamplerArg", pTestSampler );
+ }
+
+ {
+ RefCntAutoPtr<IPipelineState> pTestPSO;
+ pScript->GetPipelineStateByName( "TestVertexLayoutPSO", &pTestPSO );
+ pScript->Run( "TestVertexDescInPSO", pTestPSO );
+ }
+
+ {
+ RefCntAutoPtr<IShader> pTestVS;
+ pScript->GetShaderByName( "TestVS", &pTestVS );
+ pScript->Run( "TestShaderArg", pTestVS );
+ }
+
+ {
+ RefCntAutoPtr<IBuffer> pTestBuffer;
+ pScript->GetBufferByName( "TestBuffer", &pTestBuffer );
+ const auto &Desc = pTestBuffer->GetDesc();
+ assert( strcmp(Desc.Name, "Test Buffer") == 0 );
+ assert( Desc.Usage == USAGE_DEFAULT );
+ assert( Desc.BindFlags == (BIND_VERTEX_BUFFER | BIND_SHADER_RESOURCE) );
+
+ pScript->Run( "TestBufferArg", pTestBuffer );
+ }
+
+ {
+ pScript->Run( "TestTextureArg", pTestGlobalTexture );
+ }
+
+ {
+ DrawAttribs DrawAttribs;
+ DrawAttribs.Topology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttribs.NumVertices = 34;
+ DrawAttribs.IndexType = VT_UINT16;
+ DrawAttribs.IsIndexed = True;
+ DrawAttribs.NumInstances = 139;
+ DrawAttribs.IsIndirect = True;
+ DrawAttribs.BaseVertex = 937;
+ DrawAttribs.IndirectDrawArgsOffset = 1205;
+ DrawAttribs.StartVertexLocation = 198;
+ pScript->Run( "TestDrawAttribsArg", DrawAttribs );
+ }
+
+ {
+ RefCntAutoPtr<ITextureView> pDefaultTestTextureSRV;
+ pScript->GetTextureViewByName( "DefaultTestSRV", &pDefaultTestTextureSRV );
+ assert( pDefaultTestTextureSRV );
+ RefCntAutoPtr<ITexture> pTestTestTexture;
+ pScript->GetTextureByName( "TestTexture", &pTestTestTexture );
+ assert(pTestTestTexture );
+ assert( pDefaultTestTextureSRV == pTestTestTexture->GetDefaultView( TEXTURE_VIEW_SHADER_RESOURCE ) );
+ }
+
+ auto DevType = pRenderDevice->GetDeviceCaps().DevType;
+ if( DevType == DeviceType::D3D11 || DevType == DeviceType::D3D12 )
+ {
+ {
+ RefCntAutoPtr<ITextureView> pTestTestTextureView;
+ pScript->GetTextureViewByName( "TestTextureView", &pTestTestTextureView );
+ const auto &Desc = pTestTestTextureView->GetDesc();
+ assert( strcmp(Desc.Name, "TestTextureSRV") == 0 );
+ assert( Desc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE );
+ assert( Desc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY );
+ assert( Desc.Format == TEX_FORMAT_RGBA8_UNORM );
+ assert( Desc.MostDetailedMip == 1 );
+ assert( Desc.NumMipLevels == 2 );
+ assert( Desc.FirstArraySlice == 3 );
+ assert( Desc.NumArraySlices == 4 );
+
+ pScript->Run( "TestTextureViewArg", pTestTestTextureView );
+ }
+ }
+
+ {
+ RefCntAutoPtr<IResourceMapping> pResMapping;
+ pScript->GetResourceMappingByName( "TestResourceMapping", &pResMapping );
+ RefCntAutoPtr<IDeviceObject> pSRV, pBuff;
+ pResMapping->GetResource( "TestShaderName", &pSRV );
+ assert( pSRV != nullptr );
+ pResMapping->GetResource( "TestBufferName", &pBuff );
+ assert( pBuff != nullptr );
+ }
+
+ {
+ {
+ ResourceMappingEntry Entries[] = {
+ { "TestGlobalTextureSRV2", pTestGlobalTexture->GetDefaultView( TEXTURE_VIEW_SHADER_RESOURCE ) },
+ ResourceMappingEntry()
+ };
+ ResourceMappingDesc ResMappingDesc;
+ ResMappingDesc.pEntries = Entries;
+ RefCntAutoPtr<IResourceMapping> pResMapping;
+ pRenderDevice->CreateResourceMapping( ResMappingDesc, &pResMapping );
+ pScript->Run( "TestResourceMappingArg", pResMapping );
+ RefCntAutoPtr<IDeviceObject> pRes;
+ pResMapping->GetResource( "TestBufferName", &pRes );
+ assert( pRes != nullptr );
+ }
+ }
+
+ {
+ RefCntAutoPtr<IBuffer> pBuffer;
+ pScript->GetBufferByName( "TestGlobalBufferWithUAV", &pBuffer );
+ RefCntAutoPtr<IBufferView> pBuffUAV;
+ BufferViewDesc BuffViewDesc;
+ BuffViewDesc.Name = "TestGlobalBuff2UAV";
+ BuffViewDesc.ViewType = BUFFER_VIEW_UNORDERED_ACCESS;
+ BuffViewDesc.ByteOffset = 0;
+ BuffViewDesc.ByteWidth = 32;
+ pBuffer->CreateView(BuffViewDesc, &pBuffUAV);
+
+ pScript->Run( "TestBufferViewArg", pBuffUAV );
+ }
+
+ {
+ RefCntAutoPtr<IShaderVariable> pShaderVar;
+ pScript->GetShaderVariableByName( "svTestBlock", &pShaderVar );
+ assert( pShaderVar );
+
+ pScript->SetGlobalVariable( "svTestBlock", pShaderVar );
+ pScript->Run( "TestShaderVariable", pShaderVar );
+ }
+}
diff --git a/Tests/TestApp/src/RingBufferTest.cpp b/Tests/TestApp/src/RingBufferTest.cpp
new file mode 100644
index 0000000..9ab5dad
--- /dev/null
+++ b/Tests/TestApp/src/RingBufferTest.cpp
@@ -0,0 +1,132 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "RingBuffer.h"
+#include "DefaultRawMemoryAllocator.h"
+#include "DebugUtilities.h"
+
+using namespace Diligent;
+
+class RingBufferTest
+{
+public:
+ RingBufferTest();
+};
+
+static RingBufferTest TheRingBufferTest;
+
+RingBufferTest::RingBufferTest()
+{
+ auto &Allocator = DefaultRawMemoryAllocator::GetAllocator();
+ {
+ RingBuffer RB(1024, Allocator);
+
+ auto Offset = RB.Allocate(256);
+ VERIFY_EXPR(Offset == 0);
+
+ Offset = RB.Allocate(256);
+ VERIFY_EXPR(Offset == 256);
+
+ RB.FinishCurrentFrame(0);
+
+ Offset = RB.Allocate(256);
+ VERIFY_EXPR(Offset == 512);
+
+ Offset = RB.Allocate(256);
+ VERIFY_EXPR(Offset == 768);
+
+ RB.FinishCurrentFrame(1);
+ VERIFY_EXPR(RB.IsFull());
+
+ Offset = RB.Allocate(256);
+ VERIFY_EXPR(Offset == RingBuffer::InvalidOffset);
+
+ RingBuffer RB1(std::move(RB));
+ RB1.ReleaseCompletedFrames(2);
+ VERIFY_EXPR(RB1.IsEmpty());
+
+ VERIFY_EXPR(RB1.GetUsedSize() == 0);
+
+ Offset = RB1.Allocate(256);
+ VERIFY_EXPR(Offset == 0);
+
+ Offset = RB1.Allocate(256);
+ VERIFY_EXPR(Offset == 256);
+ RB1.FinishCurrentFrame(2);
+ RB1.ReleaseCompletedFrames(3);
+
+ VERIFY_EXPR(RB1.GetUsedSize() == 0);
+ VERIFY_EXPR(RB1.IsEmpty());
+
+ Offset = RB1.Allocate(256);
+ VERIFY_EXPR(Offset == 512);
+
+ Offset = RB1.Allocate(512);
+ VERIFY_EXPR(Offset == 0);
+
+ VERIFY_EXPR(RB1.IsFull());
+ Offset = RB1.Allocate(1);
+ VERIFY_EXPR(Offset == RingBuffer::InvalidOffset);
+ RB1.FinishCurrentFrame(3);
+
+ RB = std::move(RB1);
+ RB.ReleaseCompletedFrames(4);
+ VERIFY_EXPR(RB.GetUsedSize() == 0);
+ VERIFY_EXPR(RB.IsEmpty());
+
+ Offset = RB.Allocate(256);
+ VERIFY_EXPR(Offset == 512);
+ Offset = RB.Allocate(512+1);
+ VERIFY_EXPR(Offset == RingBuffer::InvalidOffset);
+ Offset = RB.Allocate(256);
+ VERIFY_EXPR(Offset == 768);
+ Offset = RB.Allocate(256);
+ VERIFY_EXPR(Offset == 0);
+ Offset = RB.Allocate(256+1);
+ VERIFY_EXPR(Offset == RingBuffer::InvalidOffset);
+ RB.FinishCurrentFrame(5);
+ RB.ReleaseCompletedFrames(6);
+ }
+
+ {
+ RingBuffer RB(1024, Allocator);
+ auto offset = RB.Allocate(512);
+ RB.FinishCurrentFrame(0);
+ RB.FinishCurrentFrame(1);
+ RB.ReleaseCompletedFrames(2);
+ RB.FinishCurrentFrame(2);
+ RB.FinishCurrentFrame(3);
+ offset = RB.Allocate(512);
+ RB.FinishCurrentFrame(4);
+ RB.ReleaseCompletedFrames(3);
+ RB.ReleaseCompletedFrames(4);
+ RB.ReleaseCompletedFrames(5);
+ offset = RB.Allocate(512);
+ RB.FinishCurrentFrame(5);
+ RB.ReleaseCompletedFrames(6);
+ }
+}
diff --git a/Tests/TestApp/src/ShaderConverterTest.cpp b/Tests/TestApp/src/ShaderConverterTest.cpp
new file mode 100644
index 0000000..7173a10
--- /dev/null
+++ b/Tests/TestApp/src/ShaderConverterTest.cpp
@@ -0,0 +1,73 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "ShaderConverterTest.h"
+#include "FileSystem.h"
+#include "Errors.h"
+#include "ScriptParser.h"
+#include "ConvenienceFunctions.h"
+#include "BasicShaderSourceStreamFactory.h"
+#include "HLSL2GLSLConverter.h"
+
+using namespace Diligent;
+
+ShaderConverterTest::ShaderConverterTest( IRenderDevice *pRenderDevice, IDeviceContext *pContext )
+{
+ ShaderCreationAttribs CreationAttrs;
+ CreationAttrs.FilePath = "Shaders\\ConverterTest.fx";
+ BasicShaderSourceStreamFactory BasicSSSFactory("Shaders");
+ CreationAttrs.pShaderSourceStreamFactory = &BasicSSSFactory;
+ CreationAttrs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
+ CreationAttrs.Desc.Name = "Test converted shader";
+ RefCntAutoPtr<IHLSL2GLSLConversionStream> pStream;
+ CreationAttrs.ppConversionStream = pStream.GetRawDblPtr();
+
+ {
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_PIXEL;
+ CreationAttrs.EntryPoint = "TestPS";
+ RefCntAutoPtr<IShader> pShader;
+ pRenderDevice->CreateShader( CreationAttrs, &pShader );
+ VERIFY_EXPR( pShader );
+ }
+
+ {
+ CreationAttrs.EntryPoint = "TestVS";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ RefCntAutoPtr<IShader> pShader;
+ pRenderDevice->CreateShader( CreationAttrs, &pShader );
+ VERIFY_EXPR( pShader );
+ }
+
+ {
+ CreationAttrs.FilePath = "Shaders\\CSConversionTest.fx";
+ CreationAttrs.EntryPoint = "TestCS";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_COMPUTE;
+ RefCntAutoPtr<IShader> pShader;
+ //pRenderDevice->CreateShader( CreationAttrs, &pShader );
+ //VERIFY_EXPR( pShader );
+ }
+}
diff --git a/Tests/TestApp/src/SmartPointerTest.cpp b/Tests/TestApp/src/SmartPointerTest.cpp
new file mode 100644
index 0000000..dbeed7f
--- /dev/null
+++ b/Tests/TestApp/src/SmartPointerTest.cpp
@@ -0,0 +1,746 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include <thread>
+#include "SmartPointerTest.h"
+#include "Errors.h"
+#include "DefaultRawMemoryAllocator.h"
+
+using namespace Diligent;
+
+template<typename Type>
+Type* MakeNewObj()
+{
+ return MakeNewRCObj<Type>().operator()();
+}
+
+void SmartPointerTest::CreateObject(Object **ppObj)
+{
+ *ppObj = MakeNewObj<Object>();
+ (*ppObj)->AddRef();
+}
+
+void SmartPointerTest::WaitForThreadStart(int VarId)
+{
+ std::unique_lock<std::mutex> lk(m_Mtx);
+ m_CondVar.wait(lk, [&]{return m_bThreadStart[VarId] || m_bStopThreads;});
+}
+
+void SmartPointerTest::StartThreadsAndWait(int VarId, size_t NumThreads)
+{
+ {
+ std::unique_lock<std::mutex> lk(m_Mtx);
+ m_bThreadStart[VarId] = true;
+ m_NumThreadsCompleted = 0;
+ }
+ m_CondVar.notify_all();
+
+ while((size_t)m_NumThreadsCompleted < NumThreads)
+ std::this_thread::yield();
+ m_bThreadStart[VarId] = false;
+ VERIFY_EXPR(m_NumThreadsCompleted == NumThreads);
+}
+
+void SmartPointerTest::WorkerThreadFunc(SmartPointerTest *This, size_t ThreadNum)
+{
+ while(!This->m_bStopThreads)
+ {
+ for(int i =0; i < NumThreadInterations; ++i)
+ {
+ // Wait until main() sends data
+ This->WaitForThreadStart(0);
+ if(This->m_bStopThreads)
+ {
+ This->m_NumThreadsCompleted++;
+ return;
+ }
+
+ {
+ auto *pObject = This->m_pSharedObject;
+ for(int j=0; j < 100; ++j)
+ {
+ //LOG_INFO_MESSAGE("t",std::this_thread::get_id(), ": AddRef" );
+ pObject->m_Value++;
+ pObject->AddRef();
+ }
+ This->m_NumThreadsCompleted++;
+
+ This->WaitForThreadStart(1);
+ for(int j=0; j < 100; ++j)
+ {
+ //LOG_INFO_MESSAGE("t",std::this_thread::get_id(), ": Release" );
+ pObject->m_Value--;
+ pObject->Release();
+ }
+ This->m_NumThreadsCompleted++;
+ }
+
+ {
+ This->WaitForThreadStart(0);
+ auto *pObject = This->m_pSharedObject;
+ auto *pRefCounters = pObject->GetReferenceCounters();
+ if (ThreadNum % 3 == 0)
+ {
+ pObject->m_Value++;
+ pObject->AddRef();
+ }
+ else
+ pRefCounters->AddWeakRef();
+ This->m_NumThreadsCompleted++;
+
+ This->WaitForThreadStart(1);
+ if (ThreadNum % 3 == 0)
+ {
+ pObject->m_Value--;
+ pObject->Release();
+ }
+ else
+ pRefCounters->ReleaseWeakRef();
+ This->m_NumThreadsCompleted++;
+ }
+
+ {
+ // Test interferences of ReleaseStrongRef() and GetObject()
+
+ // Goal: catch scenario when GetObject() runs between
+ // AtomicDecrement() and acquiring the lock in ReleaseStrongRef():
+
+ // m_lNumStrongReferences == 1
+ //
+
+ // Scenario I
+ //
+ // Thread 1 | Thread 2 | Thread 3
+ // | |
+ // | |
+ // | |
+ // | 1. Acquire the lock |
+ // | 2. Increment m_lNumStrongReferences |
+ // 1. Decrement m_lNumStrongReferences | 3. Read StrongRefCnt > 1 |
+ // 2. Test RefCount!=0 | 4. Return the reference to object |
+ // 3. DO NOT destroy the object | |
+ // 4. Wait for the lock | |
+
+
+ // Scenario I
+ //
+ // Thread 1 | Thread 2 | Thread 3
+ // | |
+ // | |
+ // 1. Decrement m_lNumStrongReferences | |
+ // | 1. Acquire the lock |
+ // 2. Test RefCount==0 | 2. Increment m_lNumStrongReferences |
+ // 3. Start destroying the object | 3. Read StrongRefCnt == 1 |
+ // 4. Wait for the lock | 4. DO NOT create the object |
+ // | 5. Decrement m_lNumStrongReferences |
+ // | | 1. Acquire the lock
+ // | | 2. Increment m_lNumStrongReferences
+ // | | 3. Read StrongRefCnt == 1
+ // | | 4. DO NOT create the object
+ // | | 5. Decrement m_lNumStrongReferences
+ // 5. Acquire the lock |
+ // 6. DESTROY the object |
+
+ This->WaitForThreadStart(0);
+ auto *pObject = This->m_pSharedObject;
+ RefCntWeakPtr<Object> weakPtr(pObject);
+ RefCntAutoPtr<Object> strongPtr, strongPtr2;
+ if (ThreadNum < 2)
+ {
+ strongPtr = pObject;
+ strongPtr->m_Value++;
+ }
+ else
+ weakPtr = WeakPtr(pObject);
+ This->m_NumThreadsCompleted++;
+
+ This->WaitForThreadStart(1);
+ if (ThreadNum == 0)
+ {
+ strongPtr->m_Value--;
+ strongPtr.Release();
+ }
+ else
+ {
+ strongPtr2 = weakPtr.Lock();
+ if(strongPtr2)
+ strongPtr2->m_Value++;
+ weakPtr.Release();
+ }
+ This->m_NumThreadsCompleted++;
+ }
+
+
+ {
+ This->WaitForThreadStart(0);
+ auto *pObject = This->m_pSharedObject;
+ RefCntWeakPtr<Object> weakPtr;
+ RefCntAutoPtr<Object> strongPtr;
+ if (ThreadNum % 4 == 0)
+ {
+ strongPtr = pObject;
+ strongPtr->m_Value++;
+ }
+ else
+ weakPtr = WeakPtr(pObject);
+ This->m_NumThreadsCompleted++;
+
+ This->WaitForThreadStart(1);
+ if (ThreadNum % 4 == 0)
+ {
+ strongPtr->m_Value--;
+ strongPtr.Release();
+ }
+ else
+ {
+ auto Ptr = weakPtr.Lock();
+ if(Ptr)
+ Ptr->m_Value++;
+ Ptr.Release();
+ }
+ This->m_NumThreadsCompleted++;
+ }
+ }
+ }
+}
+
+void SmartPointerTest::StartConcurrencyTest()
+{
+ auto numCores = std::thread::hardware_concurrency();
+ m_Threads.resize(numCores);
+ for(auto &t : m_Threads)
+ t = std::thread(WorkerThreadFunc, this, &t-m_Threads.data());
+}
+
+SmartPointerTest::~SmartPointerTest()
+{
+ m_bStopThreads = true;
+ StartThreadsAndWait(0, m_Threads.size());
+
+ for(auto &t : m_Threads)
+ t.join();
+
+ auto NumIterations = NumThreadInterations;
+ LOG_INFO_MESSAGE("SmartPointerTest: performed ", m_NumTestsPerformed, " concurrency tests with ", NumIterations, " iterations each");
+}
+
+void SmartPointerTest::RunConcurrencyTest()
+{
+ for(int i=0;i<NumThreadInterations; ++i)
+ {
+ m_pSharedObject = MakeNewObj<Object>();
+
+ StartThreadsAndWait(0, m_Threads.size());
+
+ StartThreadsAndWait(1, m_Threads.size());
+
+ m_pSharedObject = MakeNewObj<Object>();
+
+ StartThreadsAndWait(0, m_Threads.size());
+
+ StartThreadsAndWait(1, m_Threads.size());
+
+ m_pSharedObject = MakeNewObj<Object>();
+
+ StartThreadsAndWait(0, m_Threads.size());
+
+ StartThreadsAndWait(1, m_Threads.size());
+
+ m_pSharedObject = MakeNewObj<Object>();
+
+ StartThreadsAndWait(0, m_Threads.size());
+
+ StartThreadsAndWait(1, m_Threads.size());
+ }
+ ++m_NumTestsPerformed;
+}
+
+
+SmartPointerTest::SmartPointerTest() :
+ m_bThreadStart{false, false},
+ m_NumThreadsCompleted(0),
+ m_pSharedObject(nullptr)
+{
+ // Test constructors of RefCntAutoPtr
+ {
+ SmartPtr SP0;
+ SmartPtr SP1(nullptr);
+ auto *pRawPtr = MakeNewObj<Object>();
+ SmartPtr SP2(pRawPtr);
+ SmartPtr SP2_1(pRawPtr);
+
+ SmartPtr SP3(SP0);
+ SmartPtr SP4(SP2);
+ SmartPtr SP5(std::move(SP3));
+ SmartPtr SP6(std::move(SP4));
+ }
+
+ // Test Attach/Detach
+ {
+ {
+ SmartPtr SP0;
+ auto *pRawPtr = MakeNewObj<Object>();
+ SP0.Attach(nullptr);
+ SP0.Attach(pRawPtr);
+ pRawPtr->AddRef();
+ }
+
+ {
+ SmartPtr SP0;
+ auto *pRawPtr = MakeNewObj<Object>();
+ pRawPtr->AddRef();
+ SP0.Attach(pRawPtr);
+ SP0.Attach(nullptr);
+ }
+
+ {
+ SmartPtr SP0(MakeNewObj<Object>());
+ auto *pRawPtr = MakeNewObj<Object>();
+ SP0.Attach(pRawPtr);
+ pRawPtr->AddRef();
+ }
+
+ {
+ SmartPtr SP0(MakeNewObj<Object>());
+ auto *pRawPtr = MakeNewObj<Object>();
+ pRawPtr->AddRef();
+ SP0.Attach(pRawPtr);
+ auto *pRawPtr2 = SP0.Detach();
+ pRawPtr2->Release();
+
+ auto *pRawPtr3 = SmartPtr().Detach();
+ auto *pRawPtr4 = SmartPtr(MakeNewObj<Object>()).Detach();
+ pRawPtr4->Release();
+ }
+ }
+
+ // Test operator =
+ {
+ SmartPtr SP0;
+ auto pRawPtr1 = MakeNewObj<Object>();
+ SmartPtr SP1(pRawPtr1);
+ SmartPtr SP2(pRawPtr1);
+ SP0 = SP0;
+ SP0 = std::move(SP0);
+ SP0 = nullptr;
+ assert(SP0 == nullptr);
+
+ SP1 = pRawPtr1;
+ SP1 = SP1;
+ SP1 = std::move(SP1);
+ assert(SP1 == pRawPtr1);
+
+ SP1 = SP2;
+ SP1 = std::move(SP2);
+ assert(SP1 == pRawPtr1);
+
+ auto pRawPtr2 = MakeNewObj<Object>();
+ SmartPtr SP3(pRawPtr2);
+
+ SP0 = pRawPtr2;
+ SmartPtr SP4;
+ SP4 = SP3;
+ SmartPtr SP5;
+ SP5 = std::move(SP4);
+
+ SP1 = pRawPtr2;
+ SP1 = nullptr;
+ SP1 = std::move(SP5);
+ }
+
+ // Test logical operators
+ {
+ auto pRawPtr1 = MakeNewObj<Object>();
+ auto pRawPtr2 = MakeNewObj<Object>();
+ SmartPtr SP0, SP1(pRawPtr1), SP2(pRawPtr1), SP3(pRawPtr2);
+ assert( !SP0 );
+ bool b1 = SP0.operator bool();
+ assert( !b1 );
+ if(SP0)
+ assert( false );
+
+ assert( !(!SP1) );
+ assert( SP1 );
+ assert( SP0 != SP1 );
+ assert( SP0 == SP0 );
+ assert( SP1 == SP1 );
+ assert( SP1 == SP2 );
+ assert( SP1 != SP3 );
+ assert( SP0 < SP3 );
+ assert( (SP1 < SP3) == (pRawPtr1<pRawPtr2) );
+ }
+
+ // Test operator &
+ {
+ SmartPtr SP0, SP1(MakeNewObj<Object>()), SP2, SP3, SP4(MakeNewObj<Object>());
+ auto *pRawPtr = MakeNewObj<Object>();
+ pRawPtr->AddRef();
+
+ *static_cast<Object**>(&SP0) = pRawPtr;
+ SP0.Detach();
+ *&SP2 = pRawPtr;
+ SP2.Detach();
+
+ CreateObject(&SP3);
+
+ CreateObject(&SP1);
+ *static_cast<Object**>(&SP4) = pRawPtr;
+
+ {
+ SmartPtr SP5(MakeNewObj<Object>());
+ auto pDblPtr = &SP5;
+ *pDblPtr = MakeNewObj<Object>();
+ (*pDblPtr)->AddRef();
+ auto pDblPtr2 = &SP5;
+ CreateObject(pDblPtr2);
+ }
+
+ SmartPtr SP6(MakeNewObj<Object>());
+ // This will not work:
+ // Object **pDblPtr3 = &SP6;
+ // *pDblPtr3 = new Object;
+ }
+
+ // Test constructors of RefCntWeakPtr
+ {
+ SmartPtr SP0, SP1(MakeNewObj<Object>());
+ WeakPtr WP0;
+ WeakPtr WP1(WP0);
+ WeakPtr WP2(SP0);
+ WeakPtr WP3(SP1);
+ WeakPtr WP4(WP3);
+ WeakPtr WP5(std::move(WP0));
+ WeakPtr WP6(std::move(WP4));
+
+ auto *pRawPtr = MakeNewObj<Object>();
+ pRawPtr->AddRef();
+ WeakPtr WP7(pRawPtr);
+ pRawPtr->Release();
+ }
+
+ // Test operator =
+ {
+ auto *pRawPtr = MakeNewObj<Object>();
+ SmartPtr SP0, SP1(pRawPtr);
+ WeakPtr WP0, WP1(SP1), WP2(SP1);
+ WP0 = WP0;
+ WP0 = std::move(WP0);
+ WP1 = WP1;
+ WP1 = std::move(WP1);
+ WP1 = WP2;
+ WP1 = std::move(WP2);
+ WP1 = pRawPtr;
+ WP0 = pRawPtr;
+ WP0.Release();
+ WP0 = WP2;
+
+ WP1 = WP0;
+ WP0 = SP1;
+ WP2 = std::move(WP1);
+ }
+
+ // Test logical operators
+ {
+ SmartPtr SP0, SP1(MakeNewObj<Object>());
+ WeakPtr WP0, WP1(SP0), WP2(SP1), WP3(SP1);
+ assert( WP0 == WP1 );
+ assert( WP0 != WP2 );
+ assert( WP2 == WP3 );
+ SP1.Release();
+ assert( WP2 == WP3 );
+ }
+
+ // Test Lock()
+ {
+ SmartPtr SP0, SP1(MakeNewObj<Object>());
+ WeakPtr WP0, WP1(SP0), WP2(SP1);
+ WeakPtr WP3(WP2);
+ auto L1 = WP0.Lock();
+ assert( !L1 );
+ L1 = WP1.Lock();
+ assert( !L1 );
+ L1 = WP2.Lock();
+ assert( L1 );
+ L1 = WP3.Lock();
+ assert( L1 );
+ auto pRawPtr = SP1.Detach();
+ L1.Release();
+
+ L1 = WP3.Lock();
+ assert( L1 );
+ L1.Release();
+
+ pRawPtr->Release();
+
+ L1 = WP3.Lock();
+ assert( !L1 );
+ }
+
+ {
+ class OwnerTest : public RefCountedObject<IObject>
+ {
+ public:
+ OwnerTest(IReferenceCounters *pRefCounters) :
+ RefCountedObject<IObject>(pRefCounters),
+ Obj( NEW_RC_OBJ( DefaultRawMemoryAllocator::GetAllocator(), "Test object", Object, this)())
+ {
+ }
+
+ virtual void QueryInterface( const INTERFACE_ID &IID, IObject **ppInterface ){}
+ ~OwnerTest()
+ {
+ Obj->~Object();
+ DefaultRawMemoryAllocator::GetAllocator().Free(Obj);
+ }
+ private:
+ Object *Obj;
+ };
+
+ OwnerTest *pOwnerObject = MakeNewObj<OwnerTest>();
+ pOwnerObject->AddRef();
+ pOwnerObject->Release();
+ }
+
+ {
+ class SelfRefTest : public RefCountedObject<IObject>
+ {
+ public:
+ SelfRefTest(IReferenceCounters *pRefCounters) :
+ RefCountedObject<IObject>(pRefCounters),
+ wpSelf( this )
+ {}
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface ){}
+ private:
+ Diligent::RefCntWeakPtr<SelfRefTest> wpSelf;
+ };
+
+ SelfRefTest *pSelfRefTest = MakeNewObj<SelfRefTest>();
+ pSelfRefTest->AddRef();
+ pSelfRefTest->Release();
+ }
+
+ {
+ class ExceptionTest1 : public RefCountedObject<IObject>
+ {
+ public:
+ ExceptionTest1(IReferenceCounters *pRefCounters) :
+ RefCountedObject<IObject>(pRefCounters),
+ wpSelf(this)
+ {
+ throw std::runtime_error("test exception");
+ }
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface ){}
+ private:
+ Diligent::RefCntWeakPtr<ExceptionTest1> wpSelf;
+ };
+
+ try
+ {
+ auto *pExceptionTest = MakeNewObj<ExceptionTest1>();
+ }
+ catch(std::runtime_error &)
+ {
+
+ }
+ }
+
+ {
+ class ExceptionTest2 : public RefCountedObject<IObject>
+ {
+ public:
+ ExceptionTest2(IReferenceCounters *pRefCounters) :
+ RefCountedObject<IObject>(pRefCounters),
+ wpSelf(this)
+ {
+ throw std::runtime_error("test exception");
+ }
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface ){}
+ private:
+ Diligent::RefCntWeakPtr<ExceptionTest2> wpSelf;
+ };
+
+ try
+ {
+ auto *pExceptionTest = NEW_RC_OBJ( DefaultRawMemoryAllocator::GetAllocator(), "Test object", ExceptionTest2)();
+ }
+ catch(std::runtime_error &)
+ {
+
+ }
+ }
+
+ {
+ class ExceptionTest3 : public RefCountedObject<IObject>
+ {
+ public:
+ ExceptionTest3(IReferenceCounters *pRefCounters) :
+ RefCountedObject<IObject>(pRefCounters),
+ m_Member(*this)
+ {
+ }
+
+ class Subclass
+ {
+ public:
+ Subclass(ExceptionTest3 &parent) :
+ wpSelf(&parent)
+ {
+ throw std::runtime_error("test exception");
+ }
+ private:
+ Diligent::RefCntWeakPtr<ExceptionTest3> wpSelf;
+ };
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface ){}
+ private:
+ Subclass m_Member;
+ };
+
+ try
+ {
+ auto *pExceptionTest = NEW_RC_OBJ( DefaultRawMemoryAllocator::GetAllocator(), "Test object", ExceptionTest3)();
+ }
+ catch(std::runtime_error &)
+ {
+
+ }
+ }
+
+ {
+ class OwnerObject : public RefCountedObject<IObject>
+ {
+ public:
+ OwnerObject(IReferenceCounters *pRefCounters) :
+ RefCountedObject<IObject>(pRefCounters)
+ {}
+
+ void CreateMember()
+ {
+ try
+ {
+ m_pMember = NEW_RC_OBJ( DefaultRawMemoryAllocator::GetAllocator(), "Test object", ExceptionTest4, this)(*this);
+ }
+ catch (...)
+ {
+
+ }
+ }
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface ){}
+
+ class ExceptionTest4 : public RefCountedObject<IObject>
+ {
+ public:
+ ExceptionTest4(IReferenceCounters *pRefCounters, OwnerObject &owner) :
+ RefCountedObject<IObject>(pRefCounters),
+ m_Member(owner, *this)
+ {
+ }
+
+ class Subclass
+ {
+ public:
+ Subclass(OwnerObject &owner, ExceptionTest4 &parent) :
+ wpParent(&parent),
+ wpOwner(&owner)
+ {
+ throw std::runtime_error("test exception");
+ }
+ private:
+ Diligent::RefCntWeakPtr<ExceptionTest4> wpParent;
+ Diligent::RefCntWeakPtr<OwnerObject> wpOwner;
+ };
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface ){}
+ private:
+ Subclass m_Member;
+ };
+
+ RefCntAutoPtr<ExceptionTest4> m_pMember;
+ };
+
+ RefCntAutoPtr<OwnerObject> pOwner( NEW_RC_OBJ( DefaultRawMemoryAllocator::GetAllocator(), "Test object", OwnerObject)() );
+ pOwner->CreateMember();
+ }
+
+
+ {
+ class OwnerObject : public RefCountedObject<IObject>
+ {
+ public:
+ OwnerObject(IReferenceCounters *pRefCounters) :
+ RefCountedObject<IObject>(pRefCounters)
+ {
+ m_pMember = NEW_RC_OBJ( DefaultRawMemoryAllocator::GetAllocator(), "Test object", ExceptionTest4, this)(*this);
+ }
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface ){}
+
+ class ExceptionTest4 : public RefCountedObject<IObject>
+ {
+ public:
+ ExceptionTest4(IReferenceCounters *pRefCounters, OwnerObject &owner) :
+ RefCountedObject<IObject>(pRefCounters),
+ m_Member(owner, *this)
+ {
+ }
+
+ class Subclass
+ {
+ public:
+ Subclass(OwnerObject &owner, ExceptionTest4 &parent) :
+ wpParent(&parent),
+ wpOwner(&owner)
+ {
+ throw std::runtime_error("test exception");
+ }
+ private:
+ Diligent::RefCntWeakPtr<ExceptionTest4> wpParent;
+ Diligent::RefCntWeakPtr<OwnerObject> wpOwner;
+ };
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface ){}
+ private:
+ Subclass m_Member;
+ };
+
+ RefCntAutoPtr<ExceptionTest4> m_pMember;
+ };
+
+ try
+ {
+ RefCntAutoPtr<OwnerObject> pOwner( NEW_RC_OBJ( DefaultRawMemoryAllocator::GetAllocator(), "Test object", OwnerObject)() );
+ }
+ catch (...)
+ {
+
+ }
+ }
+
+ StartConcurrencyTest();
+ RunConcurrencyTest();
+}
+
diff --git a/Tests/TestApp/src/TestApp.cpp b/Tests/TestApp/src/TestApp.cpp
new file mode 100644
index 0000000..1bff9ee
--- /dev/null
+++ b/Tests/TestApp/src/TestApp.cpp
@@ -0,0 +1,493 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+
+#include <sstream>
+
+#include "PlatformDefinitions.h"
+#include "TestApp.h"
+#include "Errors.h"
+#include "StringTools.h"
+
+#if D3D11_SUPPORTED
+# include "RenderDeviceFactoryD3D11.h"
+#endif
+
+#if D3D12_SUPPORTED
+# include "RenderDeviceFactoryD3D12.h"
+#endif
+
+#if OPENGL_SUPPORTED
+# include "RenderDeviceFactoryOpenGL.h"
+#endif
+
+#include "FileSystem.h"
+#include "MapHelper.h"
+#include "RenderScriptTest.h"
+#include "ScriptParser.h"
+#include "Errors.h"
+#include "ConvenienceFunctions.h"
+#include "TestDepthStencilState.h"
+#include "TestRasterizerState.h"
+#include "TestBlendState.h"
+#include "TestVPAndSR.h"
+#if OPENGL_SUPPORTED
+#include "ShaderConverterTest.h"
+#endif
+#include "TestCopyTexData.h"
+#include "PlatformMisc.h"
+#include "TestBufferCreation.h"
+
+using namespace Diligent;
+
+TestApp::TestApp() :
+ m_AppTitle("Test app")
+{
+ for (Uint32 i = 0; i < 32; ++i)
+ {
+ auto MSB = PlatformMisc::GetMSB((1 << i) | 1);
+ VERIFY_EXPR(MSB == i);
+ }
+}
+
+TestApp::~TestApp()
+{
+ m_pMTResCreationTest->StopThreads();
+}
+
+
+void TestApp::InitializeDiligentEngine(
+#if PLATFORM_LINUX
+ void *display,
+#endif
+ void *NativeWindowHandle
+ )
+{
+ SwapChainDesc SCDesc;
+ SCDesc.SamplesCount = 1;
+ Uint32 NumDeferredCtx = 0;
+ std::vector<IDeviceContext*> ppContexts;
+ switch (m_DeviceType)
+ {
+#if D3D11_SUPPORTED
+ case DeviceType::D3D11:
+ {
+ EngineD3D11Attribs DeviceAttribs;
+#if ENGINE_DLL
+ GetEngineFactoryD3D11Type GetEngineFactoryD3D11 = nullptr;
+ // Load the dll and import GetEngineFactoryD3D11() function
+ LoadGraphicsEngineD3D11(GetEngineFactoryD3D11);
+#endif
+ ppContexts.resize(1 + NumDeferredCtx);
+ auto *pFactoryD3D11 = GetEngineFactoryD3D11();
+ pFactoryD3D11->CreateDeviceAndContextsD3D11(DeviceAttribs, &m_pDevice, ppContexts.data(), NumDeferredCtx);
+
+ if(NativeWindowHandle != nullptr)
+ pFactoryD3D11->CreateSwapChainD3D11(m_pDevice, ppContexts[0], SCDesc, NativeWindowHandle, &m_pSwapChain);
+ }
+ break;
+#endif
+
+#if D3D12_SUPPORTED
+ case DeviceType::D3D12:
+ {
+#if ENGINE_DLL
+ GetEngineFactoryD3D12Type GetEngineFactoryD3D12 = nullptr;
+ // Load the dll and import GetEngineFactoryD3D12() function
+ LoadGraphicsEngineD3D12(GetEngineFactoryD3D12);
+#endif
+ EngineD3D12Attribs EngD3D12Attribs;
+ ppContexts.resize(1 + NumDeferredCtx);
+ auto *pFactoryD3D12 = GetEngineFactoryD3D12();
+ pFactoryD3D12->CreateDeviceAndContextsD3D12(EngD3D12Attribs, &m_pDevice, ppContexts.data(), NumDeferredCtx);
+
+ if (!m_pSwapChain && NativeWindowHandle != nullptr)
+ pFactoryD3D12->CreateSwapChainD3D12(m_pDevice, ppContexts[0], SCDesc, NativeWindowHandle, &m_pSwapChain);
+ }
+ break;
+#endif
+
+#if OPENGL_SUPPORTED
+ case DeviceType::OpenGL:
+ case DeviceType::OpenGLES:
+ {
+#if !PLATFORM_MACOS
+ VERIFY_EXPR(NativeWindowHandle != nullptr);
+#endif
+#if ENGINE_DLL && (PLATFORM_WIN32 || PLATFORM_UNIVERSAL_WINDOWS)
+ // Declare function pointer
+ GetEngineFactoryOpenGLType GetEngineFactoryOpenGL = nullptr;
+ // Load the dll and import GetEngineFactoryOpenGL() function
+ LoadGraphicsEngineOpenGL(GetEngineFactoryOpenGL);
+#endif
+ auto *pFactoryOpenGL = GetEngineFactoryOpenGL();
+ EngineGLAttribs CreationAttribs;
+ CreationAttribs.pNativeWndHandle = NativeWindowHandle;
+#if PLATFORM_LINUX
+ CreationAttribs.pDisplay = display;
+#endif
+ if (NumDeferredCtx != 0)
+ {
+ LOG_ERROR_MESSAGE("Deferred contexts are not supported in OpenGL mode");
+ NumDeferredCtx = 0;
+ }
+ ppContexts.resize(1 + NumDeferredCtx);
+ pFactoryOpenGL->CreateDeviceAndSwapChainGL(
+ CreationAttribs, &m_pDevice, ppContexts.data(), SCDesc, &m_pSwapChain);
+ }
+ break;
+#endif
+
+ default:
+ LOG_ERROR_AND_THROW("Unknown device type");
+ break;
+ }
+
+ m_pImmediateContext.Attach(ppContexts[0]);
+ m_pDeferredContexts.resize(NumDeferredCtx);
+ for (Diligent::Uint32 ctx = 0; ctx < NumDeferredCtx; ++ctx)
+ m_pDeferredContexts[ctx].Attach(ppContexts[1 + ctx]);
+}
+
+void TestApp::InitializeRenderers()
+{
+ bool bUseOpenGL = m_DeviceType == DeviceType::OpenGL || m_DeviceType == DeviceType::OpenGLES;
+
+ TestRasterizerState TestRS(m_pDevice, m_pImmediateContext);
+ TestBlendState TestBS(m_pDevice, m_pImmediateContext);
+ TestDepthStencilState TestDSS(m_pDevice, m_pImmediateContext);
+ TestTextureCreation TestTexCreation(m_pDevice, m_pImmediateContext);
+ TestBufferCreation TestBuffCreation(m_pDevice, m_pImmediateContext);
+
+ m_TestGS.Init(m_pDevice, m_pImmediateContext);
+ m_TestTessellation.Init(m_pDevice, m_pImmediateContext);
+ m_pTestShaderResArrays.reset(new TestShaderResArrays(m_pDevice, m_pImmediateContext, bUseOpenGL, 0.4f, -0.9f, 0.5f, 0.5f));
+ m_pMTResCreationTest.reset(new MTResourceCreationTest(m_pDevice, m_pImmediateContext, 7));
+
+#if OPENGL_SUPPORTED
+ ShaderConverterTest ConverterTest(m_pDevice, m_pImmediateContext);
+#endif
+ TestSamplerCreation TestSamplers(m_pDevice);
+
+ RenderScriptTest LuaTest(m_pDevice, m_pImmediateContext);
+
+ m_pRenderScript = CreateRenderScriptFromFile("TestRenderScripts.lua", m_pDevice, m_pImmediateContext, [](ScriptParser *pScriptParser)
+ {
+ });
+
+ m_pTestDrawCommands.reset(new TestDrawCommands);
+ m_pTestDrawCommands->Init(m_pDevice, m_pImmediateContext, 0, 0, 1, 1);
+
+ m_pTestBufferAccess.reset(new TestBufferAccess);
+ m_pTestBufferAccess->Init(m_pDevice, m_pImmediateContext, -1, 0, 0.5, 0.5);
+
+
+ TEXTURE_FORMAT TestFormats[16] =
+ {
+ TEX_FORMAT_RGBA8_UNORM, TEX_FORMAT_RGBA8_UNORM_SRGB, TEX_FORMAT_RGBA32_FLOAT, TEX_FORMAT_RGBA16_UINT,
+ TEX_FORMAT_RGBA8_SNORM, TEX_FORMAT_RGBA8_UINT, TEX_FORMAT_RG8_UNORM, TEX_FORMAT_RG8_UINT,
+ TEX_FORMAT_RG32_FLOAT, TEX_FORMAT_RG16_UINT, TEX_FORMAT_RG8_SNORM, TEX_FORMAT_R8_UNORM,
+ TEX_FORMAT_R32_FLOAT, TEX_FORMAT_R8_SNORM, TEX_FORMAT_R8_UINT, TEX_FORMAT_R16_UINT
+ };
+
+ for (int j = 0; j < 4; ++j)
+ for (int i = 0; i < 4; ++i)
+ {
+ auto Ind = i + j * 4;
+ m_pTestTexturing[Ind].reset(new TestTexturing);
+ m_pTestTexturing[Ind]->Init(m_pDevice, m_pImmediateContext, TestFormats[Ind], bUseOpenGL, -1 + (float)i*1.f / 4.f, -1 + (float)j*1.f / 4.f, 0.9f / 4.f, 0.9f / 4.f);
+ }
+
+#if 0
+ TestCopyTexData TestCopyData(m_pDevice, m_pImmediateContext);
+#endif
+
+ TestVPAndSR TestVPAndSR(m_pDevice, m_pImmediateContext);
+
+
+
+ m_pTestCS.reset(new TestComputeShaders);
+ m_pTestCS->Init(m_pDevice, m_pImmediateContext);
+
+ m_pTestRT.reset(new TestRenderTarget);
+ m_pTestRT->Init(m_pDevice, m_pImmediateContext, -0.4f, 0.55f, 0.4f, 0.4f);
+
+ m_pMTResCreationTest->StartThreads();
+
+ float instance_offsets[] = { -0.3f, 0.0f, 0.0f, 0.0f, +0.3f, -0.3f };
+
+ {
+ m_pRenderScript->GetBufferByName("InstanceBuffer", &m_pInstBuff);
+ }
+
+ {
+ auto BuffDesc = m_pInstBuff->GetDesc();
+ BuffDesc.uiSizeInBytes = sizeof(instance_offsets);
+ //BuffDesc.BindFlags = BIND_VERTEX_BUFFER;
+ BuffDesc.Usage = USAGE_DEFAULT;
+ //Diligent::BufferData BuffData;
+ //BuffData.pData = instance_offsets;
+ //BuffData.DataSize = sizeof(instance_offsets);
+ m_pDevice->CreateBuffer(BuffDesc, Diligent::BufferData(), &m_pInstBuff2);
+ }
+
+
+ {
+ m_pRenderScript->GetBufferByName("UnfiformBuffer1", &m_pUniformBuff);
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.Name = "cbTestBlock2";
+ float UniformData[16] = { 1,1,1,1 };
+ BuffDesc.uiSizeInBytes = sizeof(UniformData);
+ BuffDesc.BindFlags = BIND_UNIFORM_BUFFER;
+ BuffDesc.Usage = USAGE_DYNAMIC;
+ BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ m_pDevice->CreateBuffer(BuffDesc, BufferData(), &m_pUniformBuff2);
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.Name = "Test Constant Buffer 3";
+ float UniformData[16] = { 1, 1, 1, 1 };
+ BuffDesc.uiSizeInBytes = sizeof(UniformData);
+ BuffDesc.BindFlags = BIND_UNIFORM_BUFFER;
+ BuffDesc.Usage = USAGE_DEFAULT;
+ BuffDesc.CPUAccessFlags = 0;
+ Diligent::BufferData BuffData;
+ BuffData.pData = UniformData;
+ BuffData.DataSize = sizeof(UniformData);
+ m_pDevice->CreateBuffer(BuffDesc, BuffData, &m_pUniformBuff3);
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.Name = "Test Constant Buffer 4";
+ float UniformData[16] = { 1, 1, 1, 1 };
+ BuffDesc.uiSizeInBytes = sizeof(UniformData);
+ BuffDesc.BindFlags = BIND_UNIFORM_BUFFER;
+ BuffDesc.Usage = USAGE_DEFAULT;
+ BuffDesc.CPUAccessFlags = 0;
+ Diligent::BufferData BuffData;
+ BuffData.pData = UniformData;
+ BuffData.DataSize = sizeof(UniformData);
+ m_pDevice->CreateBuffer(BuffDesc, BuffData, &m_pUniformBuff4);
+ }
+
+ {
+ RefCntAutoPtr<IResourceMapping> pResMapping;
+ m_pRenderScript->GetResourceMappingByName("ResMapping", &pResMapping);
+ pResMapping->AddResource("cbTestBlock3", m_pUniformBuff3, true);
+ m_pRenderScript->Run("AddConstBufferToMapping", "cbTestBlock4", m_pUniformBuff4);
+ m_pRenderScript->Run("AddConstBufferToMapping", "cbTestBlock2", m_pUniformBuff2);
+ m_pRenderScript->Run("BindShaderResources");
+ }
+
+ {
+ TextureDesc TexDesc;
+ TexDesc.Type = RESOURCE_DIM_TEX_2D;
+ TexDesc.Width = 1024;
+ TexDesc.Height = 1024;
+ TexDesc.Format = TEX_FORMAT_RGBA8_UNORM;
+ TexDesc.Usage = USAGE_DEFAULT;
+ TexDesc.BindFlags = BIND_SHADER_RESOURCE | BIND_RENDER_TARGET | BIND_UNORDERED_ACCESS;
+ TexDesc.Name = "UniqueTexture";
+
+ m_pDevice->CreateTexture(TexDesc, TextureData(), &m_pTestTex);
+
+ m_pTestTex.Release();
+ m_pDevice->CreateTexture(TexDesc, TextureData(), &m_pTestTex);
+ }
+
+ {
+ m_pImmediateContext->Flush();
+ // This is a test for possible bug in D3D12
+ TextureDesc TexDesc;
+ TexDesc.Type = RESOURCE_DIM_TEX_2D;
+ TexDesc.Width = 512;
+ TexDesc.Height = 512;
+ TexDesc.Format = TEX_FORMAT_RGBA8_UNORM_SRGB;
+ TexDesc.Usage = USAGE_DEFAULT;
+ TexDesc.BindFlags = BIND_SHADER_RESOURCE | BIND_RENDER_TARGET;
+ TexDesc.Name = "UniqueTexture";
+ RefCntAutoPtr<ITexture> pTex;
+ m_pDevice->CreateTexture(TexDesc, TextureData(), &pTex);
+ ITextureView *pRTVs[] = { pTex->GetDefaultView(TEXTURE_VIEW_RENDER_TARGET) };
+
+ {
+ MapHelper<float> UniformData(m_pImmediateContext, m_pUniformBuff, MAP_WRITE, MAP_FLAG_DISCARD);
+ UniformData[0] = UniformData[1] = UniformData[2] = UniformData[3] = 0;
+ }
+
+ {
+ MapHelper<float> UniformData(m_pImmediateContext, m_pUniformBuff2, MAP_WRITE, MAP_FLAG_DISCARD);
+ UniformData[0] = (float)sin(0)*0.1f;
+ UniformData[1] = (float)cos(0)*0.1f;
+ UniformData[2] = (float)sin(0)*0.1f;
+ UniformData[3] = 0;
+ }
+
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.NumVertices = 3;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ m_pRenderScript->Run(m_pImmediateContext, "DrawTris", DrawAttrs);
+
+ // This adds transition barrier for pTex1
+ m_pImmediateContext->SetRenderTargets(1, pRTVs, nullptr);
+ // Generate draw command to the bound render target
+ m_pImmediateContext->Draw(DrawAttrs);
+ m_pImmediateContext->SetRenderTargets(0, nullptr, nullptr);
+ // This will destroy texture and put D3D12 resource into release queue
+ pTex.Release();
+
+
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.Name = "cbTestBlock2";
+ float Data[16] = { 1,1,1,1 };
+ BuffDesc.uiSizeInBytes = sizeof(Data);
+ BuffDesc.BindFlags = BIND_UNIFORM_BUFFER;
+ BuffDesc.Usage = USAGE_DEFAULT;
+ BuffDesc.CPUAccessFlags = 0;
+ Diligent::BufferData BuffData;
+ BuffData.pData = Data;
+ BuffData.DataSize = sizeof(Data);
+ // This will result in creating and executing another command list
+ RefCntAutoPtr<IBuffer> pBuff;
+ m_pDevice->CreateBuffer(BuffDesc, BuffData, &pBuff);
+
+ // This may cause D3D12 error
+ m_pImmediateContext->Flush();
+ }
+}
+
+void TestApp::ProcessCommandLine(const char *CmdLine)
+{
+ const auto* Key = "mode=";
+ const auto *pos = strstr(CmdLine, Key);
+ if (pos != nullptr)
+ {
+ pos += strlen(Key);
+ if (_stricmp(pos, "D3D11") == 0)
+ {
+ m_DeviceType = DeviceType::D3D11;
+ }
+ else if (_stricmp(pos, "D3D12") == 0)
+ {
+ m_DeviceType = DeviceType::D3D12;
+ }
+ else if (_stricmp(pos, "GL") == 0)
+ {
+ m_DeviceType = DeviceType::OpenGL;
+ }
+ else
+ {
+ LOG_ERROR_AND_THROW("Unknown device type. Only the following types are supported: D3D11, D3D12, GL");
+ }
+ }
+ else
+ {
+ LOG_INFO_MESSAGE("Device type is not specified. Using D3D11 device");
+ m_DeviceType = DeviceType::D3D11;
+ }
+
+ switch (m_DeviceType)
+ {
+ case DeviceType::D3D11: m_AppTitle.append(" (D3D11)"); break;
+ case DeviceType::D3D12: m_AppTitle.append(" (D3D12)"); break;
+ case DeviceType::OpenGL: m_AppTitle.append(" (OpenGL)"); break;
+ default: UNEXPECTED("Unknown device type");
+ }
+}
+
+void TestApp::WindowResize(int width, int height)
+{
+ if (m_pSwapChain)
+ {
+ m_pSwapChain->Resize(width, height);
+ auto SCWidth = m_pSwapChain->GetDesc().Width;
+ auto SCHeight = m_pSwapChain->GetDesc().Height;
+
+
+ }
+}
+
+void TestApp::Update(double CurrTime, double ElapsedTime)
+{
+ m_SmartPointerTest.RunConcurrencyTest();
+ m_CurrTime = CurrTime;
+}
+
+void TestApp::Render()
+{
+ m_pImmediateContext->SetRenderTargets(0, nullptr, nullptr);
+
+ double dCurrTime = m_CurrTime;
+
+ float instance_offsets[] = { -0.3f, (float)sin(dCurrTime + 0.5)*0.1f, 0.0f, (float)sin(dCurrTime)*0.1f, +0.3f, -0.3f + (float)cos(dCurrTime)*0.1f };
+ m_pInstBuff2->UpdateData(m_pImmediateContext, sizeof(float) * 1, sizeof(float) * 5, &instance_offsets[1]);
+ m_pInstBuff->CopyData(m_pImmediateContext, m_pInstBuff2, sizeof(float) * 2, sizeof(float) * 2, sizeof(float) * 4);
+
+ {
+ MapHelper<float> UniformData(m_pImmediateContext, m_pUniformBuff, MAP_WRITE, MAP_FLAG_DISCARD);
+ UniformData[0] = UniformData[1] = UniformData[2] = UniformData[3] = (float)fabs(sin(dCurrTime));
+ }
+
+ {
+ MapHelper<float> UniformData(m_pImmediateContext, m_pUniformBuff2, MAP_WRITE, MAP_FLAG_DISCARD);
+ UniformData[0] = (float)sin(dCurrTime*3.8)*0.1f;
+ UniformData[1] = (float)cos(dCurrTime*3.2)*0.1f;
+ UniformData[2] = (float)sin(dCurrTime*3.9)*0.1f;
+ UniformData[3] = 0;
+ }
+
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.NumVertices = 3;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ m_pRenderScript->Run(m_pImmediateContext, "DrawTris", DrawAttrs);
+
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.NumIndices = 3;
+ DrawAttrs.IndexType = VT_UINT32;
+ DrawAttrs.NumInstances = 3;
+ m_pRenderScript->Run(m_pImmediateContext, "DrawTris", DrawAttrs);
+ m_pTestDrawCommands->Draw();
+ m_pTestBufferAccess->Draw((float)dCurrTime);
+
+ for (int i = 0; i<_countof(m_pTestTexturing); ++i)
+ {
+ m_pTestTexturing[i]->Draw();
+ }
+ m_pTestCS->Draw();
+ m_pTestRT->Draw();
+ m_pTestShaderResArrays->Draw();
+ m_TestGS.Draw();
+ m_TestTessellation.Draw();
+
+ m_pImmediateContext->Flush();
+ m_pImmediateContext->InvalidateState();
+}
+
+void TestApp::Present()
+{
+ m_pSwapChain->Present();
+}
diff --git a/Tests/TestApp/src/TestBlendState.cpp b/Tests/TestApp/src/TestBlendState.cpp
new file mode 100644
index 0000000..a01a2fa
--- /dev/null
+++ b/Tests/TestApp/src/TestBlendState.cpp
@@ -0,0 +1,250 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "TestBlendState.h"
+#include "ConvenienceFunctions.h"
+
+using namespace Diligent;
+
+void TestBlendState::CreateTestBS( BlendStateDesc &BSDesc )
+{
+ RefCntAutoPtr<IPipelineState> pPS0;
+ m_pDevice->CreatePipelineState( m_PSODesc, &pPS0 );
+ m_pDeviceContext->SetPipelineState(pPS0);
+#if 0
+ BSDesc.Name = "TestBS2";
+ m_pDevice->CreateBlendState( BSDesc, &pBS2 );
+ assert( pBS == pBS2 );
+ float BlendFactors[4] = { 0.8f, 0.2f, 0.3f, 0.6f };
+ m_pDeviceContext->SetBlendState( pBS );
+ m_pDeviceContext->SetBlendState( pBS2, BlendFactors );
+ m_pDeviceContext->SetBlendState( pBS2, BlendFactors, 0x12F5BA3D );
+ m_pDeviceContext->SetBlendState( pBS2, BlendFactors, 0x12F5BA3D );
+#endif
+}
+
+TestBlendState::TestBlendState( IRenderDevice *pDevice, IDeviceContext *pContext ) :
+ TestPipelineStateBase(pDevice),
+ m_pDeviceContext(pContext)
+{
+ m_PSODesc.Name = "PSO-TestBlendStates";
+ BlendStateDesc &BSDesc = m_PSODesc.GraphicsPipeline.BlendDesc;
+ BSDesc.RenderTargets[0].BlendEnable = True;
+ CreateTestBS( BSDesc );
+
+ BSDesc.AlphaToCoverageEnable = !BSDesc.AlphaToCoverageEnable;
+ CreateTestBS( BSDesc );
+
+ BSDesc.IndependentBlendEnable = !BSDesc.IndependentBlendEnable;
+ CreateTestBS( BSDesc );
+
+ BSDesc.AlphaToCoverageEnable = False;
+ BSDesc.IndependentBlendEnable = True;
+
+ const BLEND_FACTOR AlphaBlendFactors[] =
+ {
+ BLEND_FACTOR_ZERO,
+ BLEND_FACTOR_ONE,
+ BLEND_FACTOR_SRC_ALPHA,
+ BLEND_FACTOR_INV_SRC_ALPHA,
+ BLEND_FACTOR_DEST_ALPHA,
+ BLEND_FACTOR_INV_DEST_ALPHA,
+ BLEND_FACTOR_SRC_ALPHA_SAT,
+ BLEND_FACTOR_BLEND_FACTOR,
+ BLEND_FACTOR_INV_BLEND_FACTOR,
+ BLEND_FACTOR_SRC1_ALPHA,
+ BLEND_FACTOR_INV_SRC1_ALPHA,
+ };
+
+
+ for( int i = 0; i < BlendStateDesc::MaxRenderTargets; ++i )
+ {
+ auto &RT = BSDesc.RenderTargets[i];
+ RT.BlendEnable = True;
+ for( auto bf = BLEND_FACTOR_UNDEFINED + 1; bf < BLEND_FACTOR_NUM_FACTORS; ++bf )
+ {
+ if( i > 0 &&
+ (bf == BLEND_FACTOR_SRC1_COLOR ||
+ bf == BLEND_FACTOR_INV_SRC1_COLOR ||
+ bf == BLEND_FACTOR_SRC1_ALPHA ||
+ bf == BLEND_FACTOR_INV_SRC1_ALPHA) )
+ continue;
+ RT.SrcBlend = static_cast<BLEND_FACTOR>( bf );
+ CreateTestBS( BSDesc );
+ }
+
+ for( auto bf = BLEND_FACTOR_UNDEFINED + 1; bf < BLEND_FACTOR_NUM_FACTORS; ++bf )
+ {
+ if( i > 0 &&
+ (bf == BLEND_FACTOR_SRC1_COLOR ||
+ bf == BLEND_FACTOR_INV_SRC1_COLOR ||
+ bf == BLEND_FACTOR_SRC1_ALPHA ||
+ bf == BLEND_FACTOR_INV_SRC1_ALPHA) )
+ continue;
+
+ RT.DestBlend = static_cast<BLEND_FACTOR>( bf );
+ CreateTestBS( BSDesc );
+ }
+
+ RT.SrcBlend = BLEND_FACTOR_SRC_COLOR;
+ RT.DestBlend = BLEND_FACTOR_INV_SRC_COLOR;
+ RT.SrcBlendAlpha = BLEND_FACTOR_SRC_ALPHA;
+ RT.DestBlendAlpha = BLEND_FACTOR_INV_SRC_ALPHA;
+ for( auto bo = BLEND_OPERATION_UNDEFINED + 1; bo < BLEND_OPERATION_NUM_OPERATIONS; ++bo )
+ {
+ RT.BlendOp = static_cast<BLEND_OPERATION>( bo );
+ CreateTestBS( BSDesc );
+ }
+
+ for( auto bf = 0; bf < _countof(AlphaBlendFactors); ++bf )
+ {
+ auto AlphaBlend = AlphaBlendFactors[bf];
+ if( i > 0 && (AlphaBlend == BLEND_FACTOR_SRC1_ALPHA || AlphaBlend == BLEND_FACTOR_INV_SRC1_ALPHA) )
+ continue;
+
+ RT.SrcBlendAlpha = AlphaBlend;
+ CreateTestBS( BSDesc );
+ }
+
+ for( auto bf = 0; bf < _countof(AlphaBlendFactors); ++bf )
+ {
+ auto AlphaBlend = AlphaBlendFactors[bf];
+ if( i > 0 && (AlphaBlend == BLEND_FACTOR_SRC1_ALPHA || AlphaBlend == BLEND_FACTOR_INV_SRC1_ALPHA) )
+ continue;
+
+ RT.DestBlendAlpha = AlphaBlend;
+ CreateTestBS( BSDesc );
+ }
+
+ RT.SrcBlend = BLEND_FACTOR_SRC_COLOR;
+ RT.DestBlend = BLEND_FACTOR_INV_SRC_COLOR;
+ RT.SrcBlendAlpha = BLEND_FACTOR_SRC_ALPHA;
+ RT.DestBlendAlpha = BLEND_FACTOR_INV_SRC_ALPHA;
+ for( auto bo = BLEND_OPERATION_UNDEFINED + 1; bo < BLEND_OPERATION_NUM_OPERATIONS; ++bo )
+ {
+ RT.BlendOpAlpha = static_cast<BLEND_OPERATION>( bo );
+ CreateTestBS( BSDesc );
+ }
+
+ RT.RenderTargetWriteMask = COLOR_MASK_BLUE;
+ CreateTestBS( BSDesc );
+
+ RT.RenderTargetWriteMask |= COLOR_MASK_RED;
+ CreateTestBS( BSDesc );
+
+ RT.RenderTargetWriteMask |= COLOR_MASK_GREEN;
+ CreateTestBS( BSDesc );
+
+ RT.RenderTargetWriteMask |= COLOR_MASK_ALPHA;
+ CreateTestBS( BSDesc );
+ }
+
+ auto pScript = CreateRenderScriptFromFile( "BlendStateTest.lua", pDevice, pContext, [&]( Diligent::ScriptParser *pScriptParser )
+ {
+ BSDesc = BlendStateDesc();
+ BSDesc.IndependentBlendEnable = True;
+ BSDesc.AlphaToCoverageEnable = False;
+ BSDesc.RenderTargets[0].BlendEnable = True;
+ BSDesc.RenderTargets[0].SrcBlend = BLEND_FACTOR_ZERO;
+ BSDesc.RenderTargets[0].DestBlend = BLEND_FACTOR_ONE;
+ BSDesc.RenderTargets[0].BlendOp = BLEND_OPERATION_ADD;
+ BSDesc.RenderTargets[0].SrcBlendAlpha = BLEND_FACTOR_SRC_ALPHA;
+ BSDesc.RenderTargets[0].DestBlendAlpha = BLEND_FACTOR_INV_SRC_ALPHA;
+ BSDesc.RenderTargets[0].BlendOpAlpha = BLEND_OPERATION_SUBTRACT;
+ BSDesc.RenderTargets[0].RenderTargetWriteMask = COLOR_MASK_RED;
+
+ BSDesc.RenderTargets[1].BlendEnable = True;
+ BSDesc.RenderTargets[1].SrcBlend = BLEND_FACTOR_SRC_ALPHA;
+ BSDesc.RenderTargets[1].DestBlend = BLEND_FACTOR_INV_SRC_ALPHA;
+ BSDesc.RenderTargets[1].BlendOp = BLEND_OPERATION_REV_SUBTRACT;
+ BSDesc.RenderTargets[1].SrcBlendAlpha = BLEND_FACTOR_DEST_ALPHA;
+ BSDesc.RenderTargets[1].DestBlendAlpha = BLEND_FACTOR_INV_DEST_ALPHA;
+ BSDesc.RenderTargets[1].BlendOpAlpha = BLEND_OPERATION_MIN;
+ BSDesc.RenderTargets[1].RenderTargetWriteMask = COLOR_MASK_GREEN;
+
+ BSDesc.RenderTargets[2].BlendEnable = True;
+ BSDesc.RenderTargets[2].SrcBlend = BLEND_FACTOR_DEST_COLOR;
+ BSDesc.RenderTargets[2].DestBlend = BLEND_FACTOR_INV_DEST_COLOR;
+ BSDesc.RenderTargets[2].BlendOp = BLEND_OPERATION_MAX;
+ BSDesc.RenderTargets[2].SrcBlendAlpha = BLEND_FACTOR_SRC_ALPHA_SAT;
+ BSDesc.RenderTargets[2].DestBlendAlpha = BLEND_FACTOR_BLEND_FACTOR;
+ BSDesc.RenderTargets[2].BlendOpAlpha = BLEND_OPERATION_ADD;
+ BSDesc.RenderTargets[2].RenderTargetWriteMask = COLOR_MASK_BLUE;
+
+ BSDesc.RenderTargets[3].BlendEnable = True;
+ BSDesc.RenderTargets[3].SrcBlend = BLEND_FACTOR_INV_BLEND_FACTOR;
+ BSDesc.RenderTargets[3].DestBlend = BLEND_FACTOR_SRC_COLOR;
+ BSDesc.RenderTargets[3].BlendOp = BLEND_OPERATION_MAX;
+ BSDesc.RenderTargets[3].SrcBlendAlpha = BLEND_FACTOR_INV_SRC_ALPHA;
+ BSDesc.RenderTargets[3].DestBlendAlpha = BLEND_FACTOR_SRC_ALPHA;
+ BSDesc.RenderTargets[3].BlendOpAlpha = BLEND_OPERATION_ADD;
+ BSDesc.RenderTargets[3].RenderTargetWriteMask = COLOR_MASK_ALPHA;
+
+ RefCntAutoPtr<IPipelineState> pPSO;
+ pDevice->CreatePipelineState( m_PSODesc, &pPSO);
+ pScriptParser->SetGlobalVariable( "TestGlobalPSO", pPSO );
+ }
+ );
+ {
+ RefCntAutoPtr<IPipelineState> pPSOFromScript, pPSOFromScript2;
+ pScript->GetPipelineStateByName( "PSO_TestBlendState", &pPSOFromScript );
+ //pScript->GetPipelineStateByName( "TestPSO2", &pPSOFromScript2 );
+ //assert( pPSOFromScript == pBSFromScript2 );
+ const auto &PSODesc = pPSOFromScript->GetDesc();
+ const auto &BSDesc = PSODesc.GraphicsPipeline.BlendDesc;
+
+ assert( strcmp(PSODesc.Name, "TestPSO_FromScript") == 0 );
+ assert( BSDesc.IndependentBlendEnable == true );
+ assert( BSDesc.AlphaToCoverageEnable == false );
+ const auto &RT1 = BSDesc.RenderTargets[0];
+ assert( RT1.BlendEnable == true);
+ assert( RT1.SrcBlend == BLEND_FACTOR_ZERO);
+ assert( RT1.DestBlend == BLEND_FACTOR_SRC_COLOR);
+ assert( RT1.BlendOp == BLEND_OPERATION_ADD);
+ assert( RT1.SrcBlendAlpha == BLEND_FACTOR_SRC_ALPHA);
+ assert( RT1.DestBlendAlpha == BLEND_FACTOR_INV_SRC_ALPHA);
+ assert( RT1.BlendOpAlpha == BLEND_OPERATION_SUBTRACT);
+ assert( RT1.RenderTargetWriteMask == (COLOR_MASK_GREEN | COLOR_MASK_RED) );
+
+ const auto& RT3 = BSDesc.RenderTargets[2];
+ assert(RT3.BlendEnable == true);
+ assert(RT3.SrcBlend == BLEND_FACTOR_INV_DEST_ALPHA);
+ assert(RT3.DestBlend == BLEND_FACTOR_INV_DEST_COLOR);
+ assert(RT3.BlendOp == BLEND_OPERATION_ADD);
+ assert(RT3.SrcBlendAlpha == BLEND_FACTOR_BLEND_FACTOR);
+ assert(RT3.DestBlendAlpha == BLEND_FACTOR_INV_SRC_ALPHA);
+ assert(RT3.BlendOpAlpha == BLEND_OPERATION_SUBTRACT);
+ assert(RT3.RenderTargetWriteMask == (COLOR_MASK_BLUE | COLOR_MASK_ALPHA) );
+ }
+
+ {
+ BSDesc = BlendStateDesc();
+ RefCntAutoPtr<IPipelineState> pPSO;
+ m_pDevice->CreatePipelineState(m_PSODesc, &pPSO );
+ pScript->Run( m_pDeviceContext, "TestPSOArg", pPSO );
+ }
+}
diff --git a/Tests/TestApp/src/TestBufferAccess.cpp b/Tests/TestApp/src/TestBufferAccess.cpp
new file mode 100644
index 0000000..376be0e
--- /dev/null
+++ b/Tests/TestApp/src/TestBufferAccess.cpp
@@ -0,0 +1,266 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include <math.h>
+#include "TestBufferAccess.h"
+#include "MapHelper.h"
+#include "BasicShaderSourceStreamFactory.h"
+
+using namespace Diligent;
+
+TestBufferAccess::TestBufferAccess() :
+ m_fXExtent(0),
+ m_fYExtent(0)
+{}
+
+void TestBufferAccess::Init( IRenderDevice *pDevice, IDeviceContext *pContext, float fMinXCoord, float fMinYCoord, float fXExtent, float fYExtent )
+{
+ m_pRenderDevice = pDevice;
+ m_pDeviceContext = pContext;
+ auto DevType = m_pRenderDevice->GetDeviceCaps().DevType;
+ bool bUseOpenGL = DevType == DeviceType::OpenGL || DevType == DeviceType::OpenGLES;
+
+ m_fXExtent = fXExtent;
+ m_fYExtent = fYExtent;
+
+ float vertices[] = { 0.0f,0.0f,0.0f, 0.5f, 0.9f, 0.1f,
+ 0.5f,1.f,0.0f, 0.9f, 0.3f, 0.7f,
+ 1.f,0.0f,0.0f, 0.2f, 0.4f, 0.9f };
+ for(int iVert=0; iVert < 3; ++iVert)
+ {
+ vertices[iVert*6] = (vertices[iVert*6]) / (float)(NumRows+1) * fXExtent + fMinXCoord;
+ vertices[iVert*6+1] = (vertices[iVert*6+1]) / (float)(NumRows+1) * fYExtent + fMinYCoord;
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.uiSizeInBytes = sizeof(vertices);
+ BuffDesc.BindFlags = BIND_VERTEX_BUFFER;
+ Diligent::BufferData BuffData;
+ BuffData.pData = vertices;
+ BuffData.DataSize = BuffDesc.uiSizeInBytes;
+ m_pRenderDevice->CreateBuffer(BuffDesc, BuffData, &m_pVertexBuff);
+ }
+
+ for(int InstBuff = 0; InstBuff < _countof(m_pInstBuff); ++InstBuff)
+ {
+ float instance_offsets[NumInstances*2] =
+ {
+ 1.f * fXExtent / (float)(NumRows+1), InstBuff*fYExtent / (float)(NumRows+1),
+ 2.f * fXExtent / (float)(NumRows+1), InstBuff*fYExtent / (float)(NumRows+1),
+ 3.f * fXExtent / (float)(NumRows+1), InstBuff*fYExtent / (float)(NumRows+1),
+ };
+
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.uiSizeInBytes = sizeof(instance_offsets);
+ BuffDesc.BindFlags = BIND_VERTEX_BUFFER;
+ if( InstBuff == 3 )
+ {
+ BuffDesc.Usage = USAGE_DYNAMIC;
+ BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ }
+ else if( InstBuff == 4 )
+ {
+ BuffDesc.Usage = USAGE_CPU_ACCESSIBLE;
+ BuffDesc.BindFlags = BIND_NONE;
+ BuffDesc.CPUAccessFlags = CPU_ACCESS_READ;
+ }
+ else if( InstBuff == 5 )
+ {
+ BuffDesc.Usage = USAGE_CPU_ACCESSIBLE;
+ BuffDesc.BindFlags = BIND_NONE;
+ BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ }
+ else if( InstBuff == 6 )
+ {
+ BuffDesc.Usage = USAGE_CPU_ACCESSIBLE;
+ BuffDesc.BindFlags = BIND_NONE;
+ BuffDesc.CPUAccessFlags = CPU_ACCESS_READ;
+ }
+
+ Diligent::BufferData BuffData;
+ if(BuffDesc.Usage != USAGE_DYNAMIC && !(BuffDesc.Usage == USAGE_CPU_ACCESSIBLE && (BuffDesc.CPUAccessFlags & CPU_ACCESS_WRITE) != 0))
+ {
+ BuffData.pData = instance_offsets;
+ BuffData.DataSize = sizeof(instance_offsets);
+ }
+ m_pRenderDevice->CreateBuffer(BuffDesc, BuffData, &m_pInstBuff[InstBuff]);
+ }
+
+ ShaderCreationAttribs CreationAttrs;
+ BasicShaderSourceStreamFactory BasicSSSFactory;
+ CreationAttrs.pShaderSourceStreamFactory = &BasicSSSFactory;
+ CreationAttrs.Desc.TargetProfile = bUseOpenGL ? SHADER_PROFILE_GL_4_2 : SHADER_PROFILE_DX_5_0;
+
+ RefCntAutoPtr<Diligent::IShader> pVSInst, pPS;
+
+ {
+ CreationAttrs.FilePath = bUseOpenGL ? "Shaders\\minimalInstGL.vsh" : "Shaders\\minimalInstDX.vsh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ m_pRenderDevice->CreateShader( CreationAttrs, &pVSInst );
+ }
+
+ {
+ CreationAttrs.FilePath = bUseOpenGL ? "Shaders\\minimalGL.psh" : "Shaders\\minimalDX.psh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_PIXEL;
+ m_pRenderDevice->CreateShader( CreationAttrs, &pPS );
+ }
+
+
+ PipelineStateDesc PSODesc;
+ PSODesc.GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
+ PSODesc.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE;
+ PSODesc.GraphicsPipeline.BlendDesc.IndependentBlendEnable = False;
+ PSODesc.GraphicsPipeline.BlendDesc.RenderTargets[0].BlendEnable = False;
+ PSODesc.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM_SRGB;
+ PSODesc.GraphicsPipeline.NumRenderTargets = 1;
+ PSODesc.GraphicsPipeline.pVS = pVSInst;
+ PSODesc.GraphicsPipeline.pPS = pPS;
+
+ LayoutElement Elems[] =
+ {
+ LayoutElement( 0, 0, 3, Diligent::VT_FLOAT32, false, 0 ),
+ LayoutElement( 1, 0, 3, Diligent::VT_FLOAT32, false, sizeof( float ) * 3 ),
+ LayoutElement( 2, 1, 2, Diligent::VT_FLOAT32, false, 0, LayoutElement::FREQUENCY_PER_INSTANCE )
+ };
+ PSODesc.GraphicsPipeline.InputLayout.LayoutElements = Elems;
+ PSODesc.GraphicsPipeline.InputLayout.NumElements = _countof( Elems );
+ pDevice->CreatePipelineState(PSODesc, &m_pPSO);
+}
+
+void TestBufferAccess::Draw(float fTime)
+{
+ m_pDeviceContext->SetPipelineState(m_pPSO);
+ // No shader resources needed
+ //m_pDeviceContext->TransitionShaderResources(m_pPSO, nullptr);
+ //m_pDeviceContext->CommitShaderResources(nullptr);
+
+ IBuffer *pBuffs[2] = {m_pVertexBuff, m_pInstBuff[0]};
+ Uint32 Strides[] = {sizeof(float)*6, sizeof(float)*2};
+ Uint32 Offsets[] = {0, 0};
+ m_pDeviceContext->SetVertexBuffers( 0, _countof( pBuffs ), pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET );
+
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumVertices = 3;
+ DrawAttrs.NumInstances = NumInstances;
+ m_pDeviceContext->Draw(DrawAttrs);
+
+
+ float fDX = m_fXExtent / (float)(NumRows+1);
+ float fDY = m_fYExtent / (float)(NumRows+1);
+
+ float instance_offsets[NumInstances*2];
+ for(int Inst = 0; Inst < NumInstances; ++Inst)
+ {
+ instance_offsets[Inst*2] = (1+Inst) * fDX;
+ instance_offsets[Inst*2+1] = 1.f * fDY + sin(fTime) * fDY * 0.3f;
+ }
+ m_pInstBuff[1]->UpdateData( m_pDeviceContext, sizeof( float ) * 2, sizeof( float ) * 4, &instance_offsets[2] );
+
+ pBuffs[1] = m_pInstBuff[1];
+ m_pDeviceContext->SetVertexBuffers( 0, _countof( pBuffs ), pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET );
+
+ m_pDeviceContext->Draw(DrawAttrs);
+
+
+ for(int Inst = 0; Inst < NumInstances; ++Inst)
+ {
+ instance_offsets[Inst*2] = (1+Inst) * fDX;
+ instance_offsets[Inst*2+1] = 2.f * fDY + sin(fTime*0.8f) * fDY * 0.3f;
+ }
+ m_pInstBuff[2]->UpdateData( m_pDeviceContext, sizeof( float ) * 2, sizeof( float ) * 4, &instance_offsets[2] );
+ m_pInstBuff[1]->CopyData( m_pDeviceContext, m_pInstBuff[2], sizeof( float ) * 2, sizeof( float ) * 2, sizeof( float ) * 4 );
+
+ m_pDeviceContext->Draw(DrawAttrs);
+
+ for(int Inst = 0; Inst < NumInstances; ++Inst)
+ {
+ instance_offsets[Inst*2] = (1+Inst) * fDX;
+ instance_offsets[Inst*2+1] = 3.f * fDY + sin(fTime*1.2f) * fDY * 0.3f;
+ }
+
+ // Test updating dynamic buffer
+ {
+ MapHelper<float> pInstData( m_pDeviceContext, m_pInstBuff[3], MAP_WRITE, MAP_FLAG_DISCARD );
+ memcpy(pInstData, instance_offsets, sizeof(instance_offsets));
+ }
+
+ pBuffs[1] = m_pInstBuff[3];
+ m_pDeviceContext->SetVertexBuffers( 0, _countof( pBuffs ), pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET );
+
+ m_pDeviceContext->Draw(DrawAttrs);
+
+return;
+ MapHelper<float> pStagingData;
+ // Test reading data from staging resource
+ {
+ m_pInstBuff[4]->CopyData( m_pDeviceContext, m_pInstBuff[3], 0, 0, sizeof( instance_offsets ) );
+ pStagingData.Map( m_pDeviceContext, m_pInstBuff[4], MAP_READ, 0 );
+ for(int i = 0; i < _countof(instance_offsets); ++i)
+ assert(pStagingData[i] == instance_offsets[i]);
+ pStagingData.Unmap();
+ }
+
+ // D3D12 does not allow writing to the CPU-readable buffers
+ if(m_pRenderDevice->GetDeviceCaps().DevType != DeviceType::D3D12)
+ {
+ // Test writing data to staging resource
+ {
+ pStagingData.Map( m_pDeviceContext, m_pInstBuff[5], MAP_WRITE, 0 );
+ for(int Inst = 0; Inst < NumInstances; ++Inst)
+ {
+ pStagingData[Inst*2] = (1+Inst) * fDX;
+ pStagingData[Inst*2+1] = 4.f * fDY + sin(fTime*1.3f) * fDY * 0.3f;
+ }
+ pStagingData.Unmap();
+ }
+
+ m_pInstBuff[2]->CopyData( m_pDeviceContext, m_pInstBuff[5], 0, 0, sizeof( instance_offsets ) );
+ pBuffs[1] = m_pInstBuff[2];
+ m_pDeviceContext->SetVertexBuffers( 0, _countof( pBuffs ), pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET );
+ m_pDeviceContext->Draw(DrawAttrs);
+
+
+ // Test reading & writing data to the staging resource
+ /*{
+ MapHelper<float> pInstData2( m_pDeviceContext, m_pInstBuff[6], MAP_READ_WRITE, 0 );
+ MapHelper<float> pInstData3( std::move(pInstData2) );
+ MapHelper<float> pInstData;
+ pInstData = std::move(pInstData3);
+ static float fPrevTime = fTime;
+ for(int Inst = 0; Inst < NumInstances; ++Inst)
+ {
+ pInstData[Inst*2] += (fTime-fPrevTime) * sin(fTime)*0.1f * m_fXExtent;
+ }
+ fPrevTime = fTime;
+ }*/
+
+ m_pInstBuff[2]->CopyData( m_pDeviceContext, m_pInstBuff[6], 0, 0, sizeof( instance_offsets ) );
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+}
diff --git a/Tests/TestApp/src/TestBufferCreation.cpp b/Tests/TestApp/src/TestBufferCreation.cpp
new file mode 100644
index 0000000..2acaf07
--- /dev/null
+++ b/Tests/TestApp/src/TestBufferCreation.cpp
@@ -0,0 +1,137 @@
+/* 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.
+ */
+
+#include "pch.h"
+#include "TestBufferCreation.h"
+
+#if D3D11_SUPPORTED
+#include "TestCreateObjFromNativeResD3D11.h"
+#endif
+
+#if D3D12_SUPPORTED
+#include "TestCreateObjFromNativeResD3D12.h"
+#endif
+
+#if OPENGL_SUPPORTED
+#include "TestCreateObjFromNativeResGL.h"
+#endif
+
+using namespace Diligent;
+
+TestBufferCreation::TestBufferCreation(Diligent::IRenderDevice *pDevice, Diligent::IDeviceContext *pContext)
+{
+ std::unique_ptr<TestCreateObjFromNativeRes> pTestCreateObjFromNativeRes;
+ auto DevType = pDevice->GetDeviceCaps().DevType;
+ switch (DevType)
+ {
+#if D3D11_SUPPORTED
+ case DeviceType::D3D11:
+ pTestCreateObjFromNativeRes.reset(new TestCreateObjFromNativeResD3D11(pDevice));
+ break;
+
+#endif
+
+#if D3D12_SUPPORTED
+ case DeviceType::D3D12:
+ pTestCreateObjFromNativeRes.reset(new TestCreateObjFromNativeResD3D12(pDevice));
+ break;
+#endif
+
+#if OPENGL_SUPPORTED
+ case DeviceType::OpenGL:
+ case DeviceType::OpenGLES:
+ pTestCreateObjFromNativeRes.reset(new TestCreateObjFromNativeResGL(pDevice));
+ break;
+#endif
+
+ default: UNEXPECTED("Unexpected device type");
+ }
+
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.Name = "Buffer creation test 0";
+ BuffDesc.uiSizeInBytes = 256;
+ BuffDesc.BindFlags = BIND_VERTEX_BUFFER;
+ RefCntAutoPtr<IBuffer> pBuffer;
+ pDevice->CreateBuffer(BuffDesc, BufferData(), &pBuffer);
+ VERIFY_EXPR(pBuffer);
+
+ pTestCreateObjFromNativeRes->CreateBuffer(pBuffer);
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.Name = "Buffer creation test 1";
+ BuffDesc.uiSizeInBytes = 256;
+ BuffDesc.BindFlags = BIND_VERTEX_BUFFER;
+ RefCntAutoPtr<IBuffer> pBuffer;
+ pDevice->CreateBuffer(BuffDesc, BufferData(), &pBuffer);
+ VERIFY_EXPR(pBuffer);
+
+ pTestCreateObjFromNativeRes->CreateBuffer(pBuffer);
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.Name = "Buffer creation test 2";
+ BuffDesc.uiSizeInBytes = 256;
+ BuffDesc.BindFlags = BIND_INDIRECT_DRAW_ARGS | BIND_UNORDERED_ACCESS;
+ BuffDesc.Mode = BUFFER_MODE_FORMATTED;
+ BuffDesc.Format.NumComponents = 4;
+ BuffDesc.Format.ValueType = VT_INT32;
+ BuffDesc.Format.IsNormalized = false;
+ RefCntAutoPtr<IBuffer> pBuffer;
+ pDevice->CreateBuffer(BuffDesc, BufferData(), &pBuffer);
+ VERIFY_EXPR(pBuffer);
+
+ pTestCreateObjFromNativeRes->CreateBuffer(pBuffer);
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.Name = "Buffer creation test 3";
+ BuffDesc.uiSizeInBytes = 256;
+ BuffDesc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
+ BuffDesc.Mode = BUFFER_MODE_STRUCTURED;
+ BuffDesc.ElementByteStride = 16;
+ RefCntAutoPtr<IBuffer> pBuffer;
+ pDevice->CreateBuffer(BuffDesc, BufferData(), &pBuffer);
+ VERIFY_EXPR(pBuffer);
+
+ pTestCreateObjFromNativeRes->CreateBuffer(pBuffer);
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.Name = "Buffer creation test 4";
+ BuffDesc.uiSizeInBytes = 256;
+ BuffDesc.BindFlags = BIND_UNIFORM_BUFFER;
+ RefCntAutoPtr<IBuffer> pBuffer;
+ pDevice->CreateBuffer(BuffDesc, BufferData(), &pBuffer);
+ VERIFY_EXPR(pBuffer);
+
+ pTestCreateObjFromNativeRes->CreateBuffer(pBuffer);
+ }
+
+}
diff --git a/Tests/TestApp/src/TestComputeShaders.cpp b/Tests/TestApp/src/TestComputeShaders.cpp
new file mode 100644
index 0000000..43c6dd0
--- /dev/null
+++ b/Tests/TestApp/src/TestComputeShaders.cpp
@@ -0,0 +1,50 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "TestComputeShaders.h"
+#include "GraphicsUtilities.h"
+#include "ConvenienceFunctions.h"
+
+using namespace Diligent;
+
+TestComputeShaders::TestComputeShaders()
+{
+}
+
+void TestComputeShaders::Init( IRenderDevice *pDevice, IDeviceContext *pContext )
+{
+ m_pRenderDevice = pDevice;
+ m_pDeviceContext = pContext;
+ m_pRenderScript = CreateRenderScriptFromFile( "TestComputeShaders.lua", pDevice, pContext, []( ScriptParser *pScriptParser )
+ {
+ } );
+}
+
+void TestComputeShaders::Draw()
+{
+ m_pRenderScript->Run( m_pDeviceContext, "Render" );
+}
diff --git a/Tests/TestApp/src/TestCopyTexData.cpp b/Tests/TestApp/src/TestCopyTexData.cpp
new file mode 100644
index 0000000..cbd6a24
--- /dev/null
+++ b/Tests/TestApp/src/TestCopyTexData.cpp
@@ -0,0 +1,197 @@
+/* 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.
+ */
+
+#include "pch.h"
+#include "TestCopyTexData.h"
+#include "RenderDevice.h"
+#include "GraphicsUtilities.h"
+#include "Errors.h"
+
+using namespace Diligent;
+
+TestCopyTexData::TestCopyTexData( IRenderDevice *pDevice, IDeviceContext *pContext ) :
+ m_pDevice(pDevice),
+ m_pContext(pContext)
+{
+ TEXTURE_FORMAT TestFormats[] =
+ {
+ TEX_FORMAT_RGBA32_FLOAT,
+ TEX_FORMAT_RGBA32_UINT,
+ TEX_FORMAT_RGBA32_SINT,
+ TEX_FORMAT_RGBA16_FLOAT,
+ TEX_FORMAT_RGBA16_UINT,
+ TEX_FORMAT_RGBA16_SINT,
+ TEX_FORMAT_RGBA8_UNORM,
+ TEX_FORMAT_RGBA8_SNORM,
+ TEX_FORMAT_RGBA8_UINT,
+ TEX_FORMAT_RGBA8_SINT,
+
+ TEX_FORMAT_RG32_FLOAT,
+ TEX_FORMAT_RG32_UINT,
+ TEX_FORMAT_RG32_SINT,
+ TEX_FORMAT_RG16_FLOAT,
+ TEX_FORMAT_RG16_UINT,
+ TEX_FORMAT_RG16_SINT,
+ TEX_FORMAT_RG8_UNORM,
+ TEX_FORMAT_RG8_SNORM,
+ TEX_FORMAT_RG8_UINT,
+ TEX_FORMAT_RG8_SINT,
+
+ TEX_FORMAT_R32_FLOAT,
+ TEX_FORMAT_R32_UINT,
+ TEX_FORMAT_R32_SINT,
+ TEX_FORMAT_R16_FLOAT,
+ TEX_FORMAT_R16_UINT,
+ TEX_FORMAT_R16_SINT,
+ TEX_FORMAT_R8_UNORM,
+ TEX_FORMAT_R8_SNORM,
+ TEX_FORMAT_R8_UINT,
+ TEX_FORMAT_R8_SINT
+ };
+ for( auto f = 0; f < _countof( TestFormats ); ++f )
+ {
+ Test2DTexture(TestFormats[f]);
+ Test2DTexArray(TestFormats[f]);
+ Test3DTexture(TestFormats[f]);
+ }
+}
+
+void TestCopyTexData::Test2DTexture( TEXTURE_FORMAT Format )
+{
+ TextureDesc TexDesc;
+ TexDesc.Type = RESOURCE_DIM_TEX_2D;
+ TexDesc.Format = Format;
+ TexDesc.Width = 128;
+ TexDesc.Height = 128;
+ TexDesc.BindFlags = BIND_SHADER_RESOURCE;
+ TexDesc.MipLevels = 5;
+ TexDesc.Usage = USAGE_DEFAULT;
+
+ Diligent::RefCntAutoPtr<ITexture> pSrcTex, pDstTex;
+ m_pDevice->CreateTexture( TexDesc, TextureData(), &pSrcTex );
+ m_pDevice->CreateTexture( TexDesc, TextureData(), &pDstTex );
+
+ pDstTex->CopyData(m_pContext, pSrcTex,
+ 2, // Src mip
+ 0, // Src slice
+ nullptr, // Box
+ 1, // dst mip
+ 0, // dst slice
+ 32, 16, 0 // XYZ offset
+ );
+
+ Box SrcBox;
+ SrcBox.MinX = 3;
+ SrcBox.MaxX = 19;
+ SrcBox.MinY = 1;
+ SrcBox.MaxY = 32;
+ pDstTex->CopyData(m_pContext, pSrcTex,
+ 2, // Src mip
+ 0, // Src slice
+ &SrcBox, // Box
+ 1, // dst mip
+ 0, // dst slice
+ 32, 16, 0 // XYZ offset
+ );
+
+}
+
+void TestCopyTexData::Test2DTexArray( TEXTURE_FORMAT Format )
+{
+ TextureDesc TexDesc;
+ TexDesc.Type = RESOURCE_DIM_TEX_2D_ARRAY;
+ TexDesc.Format = Format;
+ TexDesc.Width = 128;
+ TexDesc.Height = 128;
+ TexDesc.BindFlags = BIND_SHADER_RESOURCE;
+ TexDesc.MipLevels = 5;
+ TexDesc.ArraySize = 8;
+ TexDesc.Usage = USAGE_DEFAULT;
+
+ Diligent::RefCntAutoPtr<ITexture> pSrcTex, pDstTex;
+ m_pDevice->CreateTexture( TexDesc, TextureData(), &pSrcTex );
+ m_pDevice->CreateTexture( TexDesc, TextureData(), &pDstTex );
+
+ pDstTex->CopyData(m_pContext, pSrcTex,
+ 2, // Src mip
+ 3, // Src slice
+ nullptr, // Box
+ 1, // dst mip
+ 6, // dst slice
+ 32, 16, 0 // XYZ offset
+ );
+
+ Box SrcBox;
+ SrcBox.MinX = 3;
+ SrcBox.MaxX = 19;
+ SrcBox.MinY = 1;
+ SrcBox.MaxY = 32;
+ pDstTex->CopyData(m_pContext, pSrcTex,
+ 2, // Src mip
+ 3, // Src slice
+ &SrcBox, // Box
+ 1, // dst mip
+ 5, // dst slice
+ 32, 16, 0 // XYZ offset
+ );
+}
+
+void TestCopyTexData::Test3DTexture( TEXTURE_FORMAT Format )
+{
+ TextureDesc TexDesc;
+ TexDesc.Type = RESOURCE_DIM_TEX_3D;
+ TexDesc.Format = Format;
+ TexDesc.Width = 64;
+ TexDesc.Height = 64;
+ TexDesc.Depth = 16;
+ TexDesc.BindFlags = BIND_SHADER_RESOURCE;
+ TexDesc.MipLevels = 4;
+ TexDesc.Usage = USAGE_DEFAULT;
+
+ Diligent::RefCntAutoPtr<ITexture> pSrcTex, pDstTex;
+ m_pDevice->CreateTexture( TexDesc, TextureData(), &pSrcTex );
+ m_pDevice->CreateTexture( TexDesc, TextureData(), &pDstTex );
+
+ pDstTex->CopyData(m_pContext, pSrcTex,
+ 2, // Src mip
+ 0, // Src slice
+ nullptr, // Box
+ 1, // dst mip
+ 0, // dst slice
+ 16, 8, 0 // XYZ offset
+ );
+
+ Box SrcBox;
+ SrcBox.MinX = 3;
+ SrcBox.MaxX = 19;
+ SrcBox.MinY = 1;
+ SrcBox.MaxY = 32;
+ pDstTex->CopyData(m_pContext, pSrcTex,
+ 1, // Src mip
+ 0, // Src slice
+ &SrcBox, // Box
+ 0, // dst mip
+ 0, // dst slice
+ 32, 16, 0 // XYZ offset
+ );
+}
diff --git a/Tests/TestApp/src/TestCreateObjFromNativeResD3D11.cpp b/Tests/TestApp/src/TestCreateObjFromNativeResD3D11.cpp
new file mode 100644
index 0000000..41794c2
--- /dev/null
+++ b/Tests/TestApp/src/TestCreateObjFromNativeResD3D11.cpp
@@ -0,0 +1,104 @@
+/* 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.
+ */
+
+#include "pch.h"
+#include "TestCreateObjFromNativeResD3D11.h"
+
+#include <d3d11.h>
+#include "RenderDeviceD3D11.h"
+#include "TextureD3D11.h"
+#include "BufferD3D11.h"
+
+using namespace Diligent;
+
+void TestCreateObjFromNativeResD3D11::CreateTexture(Diligent::ITexture *pTexture)
+{
+ RefCntAutoPtr<IRenderDeviceD3D11> pDeviceD3D11(m_pDevice, IID_RenderDeviceD3D11);
+ const auto &SrcTexDesc = pTexture->GetDesc();
+ RefCntAutoPtr<ITextureD3D11> pTextureD3D11(pTexture, IID_TextureD3D11);
+ auto *pd3d11Texture = pTextureD3D11->GetD3D11Texture();
+ RefCntAutoPtr<ITexture> pTextureFromNativeD3D11Handle;
+ if (SrcTexDesc.Type == RESOURCE_DIM_TEX_1D || SrcTexDesc.Type == RESOURCE_DIM_TEX_1D_ARRAY)
+ {
+ pDeviceD3D11->CreateTextureFromD3DResource(static_cast<ID3D11Texture1D*>(pd3d11Texture), &pTextureFromNativeD3D11Handle);
+ }
+ else if (SrcTexDesc.Type == RESOURCE_DIM_TEX_2D || SrcTexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY ||
+ SrcTexDesc.Type == RESOURCE_DIM_TEX_CUBE || SrcTexDesc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
+ {
+ pDeviceD3D11->CreateTextureFromD3DResource(static_cast<ID3D11Texture2D*>(pd3d11Texture), &pTextureFromNativeD3D11Handle);
+ }
+ else if (RESOURCE_DIM_TEX_3D)
+ {
+ pDeviceD3D11->CreateTextureFromD3DResource(static_cast<ID3D11Texture3D*>(pd3d11Texture), &pTextureFromNativeD3D11Handle);
+ }
+ else
+ {
+ UNEXPECTED("Unexpected texture dimensions");
+ }
+
+ auto TestTexDesc = pTextureFromNativeD3D11Handle->GetDesc();
+ if (SrcTexDesc.Type == RESOURCE_DIM_TEX_CUBE || SrcTexDesc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
+ {
+ VERIFY_EXPR(TestTexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY);
+ TestTexDesc.Type = SrcTexDesc.Type;
+ }
+ VERIFY_EXPR(TestTexDesc == SrcTexDesc);
+ RefCntAutoPtr<ITextureD3D11> pTestTextureD3D11(pTextureFromNativeD3D11Handle, IID_TextureD3D11);
+ VERIFY_EXPR(pTestTextureD3D11->GetD3D11Texture() == pd3d11Texture);
+ VERIFY_EXPR(pTestTextureD3D11->GetNativeHandle() == pd3d11Texture);
+}
+
+void TestCreateObjFromNativeResD3D11::CreateBuffer(Diligent::IBuffer *pBuffer)
+{
+ RefCntAutoPtr<IRenderDeviceD3D11> pDeviceD3D11(m_pDevice, IID_RenderDeviceD3D11);
+ const auto &SrcBuffDesc = pBuffer->GetDesc();
+ RefCntAutoPtr<IBufferD3D11> pBufferD3D11(pBuffer, IID_BufferD3D11);
+ auto *pd3d11Buffer = pBufferD3D11->GetD3D11Buffer();
+
+ {
+ RefCntAutoPtr<IBuffer> pBufferFromNativeD3D11Handle;
+ pDeviceD3D11->CreateBufferFromD3DResource(pd3d11Buffer, SrcBuffDesc, &pBufferFromNativeD3D11Handle);
+
+ const auto &TestBufferDesc = pBufferFromNativeD3D11Handle->GetDesc();
+ VERIFY_EXPR(TestBufferDesc == SrcBuffDesc);
+
+ RefCntAutoPtr<IBufferD3D11> pTestBufferD3D11(pBufferFromNativeD3D11Handle, IID_BufferD3D11);
+ VERIFY_EXPR(pTestBufferD3D11->GetD3D11Buffer() == pd3d11Buffer);
+ VERIFY_EXPR(pTestBufferD3D11->GetNativeHandle() == pd3d11Buffer);
+ }
+
+ {
+ BufferDesc BuffDesc;
+ BuffDesc.Name = "Test buffer from D3D11 buffer";
+ BuffDesc.Format = SrcBuffDesc.Format;
+ RefCntAutoPtr<IBuffer> pBufferFromNativeD3D11Handle;
+ pDeviceD3D11->CreateBufferFromD3DResource(pd3d11Buffer, BuffDesc, &pBufferFromNativeD3D11Handle);
+
+ const auto &TestBufferDesc = pBufferFromNativeD3D11Handle->GetDesc();
+ VERIFY_EXPR(TestBufferDesc == SrcBuffDesc);
+
+ RefCntAutoPtr<IBufferD3D11> pTestBufferD3D11(pBufferFromNativeD3D11Handle, IID_BufferD3D11);
+ VERIFY_EXPR(pTestBufferD3D11->GetD3D11Buffer() == pd3d11Buffer);
+ VERIFY_EXPR(pTestBufferD3D11->GetNativeHandle() == pd3d11Buffer);
+ }
+} \ No newline at end of file
diff --git a/Tests/TestApp/src/TestCreateObjFromNativeResD3D12.cpp b/Tests/TestApp/src/TestCreateObjFromNativeResD3D12.cpp
new file mode 100644
index 0000000..2a433a7
--- /dev/null
+++ b/Tests/TestApp/src/TestCreateObjFromNativeResD3D12.cpp
@@ -0,0 +1,77 @@
+/* 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.
+ */
+
+#include "pch.h"
+#include "TestCreateObjFromNativeResD3D12.h"
+#include <d3d12.h>
+#include "RenderDeviceD3D12.h"
+#include "TextureD3D12.h"
+#include "BufferD3D12.h"
+
+using namespace Diligent;
+
+void TestCreateObjFromNativeResD3D12::CreateTexture(Diligent::ITexture *pTexture)
+{
+ RefCntAutoPtr<IRenderDeviceD3D12> pDeviceD3D12(m_pDevice, IID_RenderDeviceD3D12);
+ const auto &SrcTexDesc = pTexture->GetDesc();
+ RefCntAutoPtr<ITextureD3D12> pTextureD3D12(pTexture, IID_TextureD3D12);
+ auto *pD3D12Texture = pTextureD3D12->GetD3D12Texture();
+ RefCntAutoPtr<ITexture> pTextureFromNativeD3D12Handle;
+ pDeviceD3D12->CreateTextureFromD3DResource(pD3D12Texture, &pTextureFromNativeD3D12Handle);
+
+ auto TestTexDesc = pTextureFromNativeD3D12Handle->GetDesc();
+ if (SrcTexDesc.Type == RESOURCE_DIM_TEX_CUBE || SrcTexDesc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
+ {
+ VERIFY_EXPR(TestTexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY);
+ TestTexDesc.Type = SrcTexDesc.Type;
+ }
+ VERIFY_EXPR(TestTexDesc == SrcTexDesc);
+
+ RefCntAutoPtr<ITextureD3D12> pTestTextureD3D12(pTextureFromNativeD3D12Handle, IID_TextureD3D12);
+ VERIFY_EXPR(pTestTextureD3D12->GetD3D12Texture() == pD3D12Texture);
+ VERIFY_EXPR(pTestTextureD3D12->GetNativeHandle() == pD3D12Texture);
+}
+
+void TestCreateObjFromNativeResD3D12::CreateBuffer(Diligent::IBuffer *pBuffer)
+{
+ RefCntAutoPtr<IRenderDeviceD3D12> pDeviceD3D12(m_pDevice, IID_RenderDeviceD3D12);
+ const auto &SrcBuffDesc = pBuffer->GetDesc();
+ RefCntAutoPtr<IBufferD3D12> pBufferD3D12(pBuffer, IID_BufferD3D12);
+ size_t DataStartByteOffset;
+ auto *pD3D12Buffer = pBufferD3D12->GetD3D12Buffer(DataStartByteOffset, 0);
+ VERIFY_EXPR(DataStartByteOffset == 0);
+
+ {
+ RefCntAutoPtr<IBuffer> pBufferFromNativeD3D12Handle;
+ pDeviceD3D12->CreateBufferFromD3DResource(pD3D12Buffer, SrcBuffDesc, &pBufferFromNativeD3D12Handle);
+
+ const auto &TestBufferDesc = pBufferFromNativeD3D12Handle->GetDesc();
+ VERIFY_EXPR(TestBufferDesc == SrcBuffDesc);
+
+ RefCntAutoPtr<IBufferD3D12> pTestBufferD3D12(pBufferFromNativeD3D12Handle, IID_BufferD3D12);
+ size_t TestBuffDataStartByteOffset;
+ VERIFY_EXPR(pTestBufferD3D12->GetD3D12Buffer(TestBuffDataStartByteOffset, 0) == pD3D12Buffer);
+ VERIFY_EXPR(TestBuffDataStartByteOffset == 0);
+ VERIFY_EXPR(pTestBufferD3D12->GetNativeHandle() == pD3D12Buffer);
+ }
+} \ No newline at end of file
diff --git a/Tests/TestApp/src/TestCreateObjFromNativeResGL.cpp b/Tests/TestApp/src/TestCreateObjFromNativeResGL.cpp
new file mode 100644
index 0000000..b21ae64
--- /dev/null
+++ b/Tests/TestApp/src/TestCreateObjFromNativeResGL.cpp
@@ -0,0 +1,141 @@
+/* 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.
+ */
+
+#include "pch.h"
+
+#if PLATFORM_WIN32
+
+# ifndef GLEW_STATIC
+# define GLEW_STATIC // Must be defined to use static version of glew
+# endif
+# include "GL/glew.h"
+ #elif PLATFORM_LINUX
+
+# ifndef GLEW_STATIC
+# define GLEW_STATIC // Must be defined to use static version of glew
+# endif
+# ifndef GLEW_NO_GLU
+# define GLEW_NO_GLU
+# endif
+
+# include "GL/glew.h"
+
+ // Undefine beautiful defines from GL/glx.h -> X11/Xlib.h
+# ifdef Bool
+# undef Bool
+# endif
+# ifdef True
+# undef True
+# endif
+# ifdef False
+# undef False
+# endif
+# ifdef Status
+# undef Status
+# endif
+# ifdef Success
+# undef Success
+# endif
+
+#elif PLATFORM_MACOS
+
+# ifndef GLEW_STATIC
+# define GLEW_STATIC // Must be defined to use static version of glew
+# endif
+# ifndef GLEW_NO_GLU
+# define GLEW_NO_GLU
+# endif
+
+# include "GL/glew.h"
+
+#elif PLATFORM_ANDROID
+
+# include <GLES3/gl3.h>
+# include <GLES3/gl3ext.h>
+ // GLStubs must be included after GLFeatures!
+# include "GLStubsAndroid.h"
+
+#elif PLATFORM_IOS
+
+# include <OpenGLES/ES3/gl.h>
+# include "GLStubsIOS.h"
+
+#else
+# error Unsupported platform
+#endif
+
+#include "RenderDeviceGL.h"
+#include "TextureGL.h"
+#include "BufferGL.h"
+
+#include "Errors.h"
+#include "TestCreateObjFromNativeResGL.h"
+
+using namespace Diligent;
+
+void TestCreateObjFromNativeResGL::CreateTexture(Diligent::ITexture *pTexture)
+{
+#if PLATFORM_WIN32 || PLATFORM_LINUX || PLATFORM_ANDROID
+ RefCntAutoPtr<IRenderDeviceGL> pDeviceGL(m_pDevice, IID_RenderDeviceGL);
+ const auto &SrcTexDesc = pTexture->GetDesc();
+ if (SrcTexDesc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
+ return;
+
+ RefCntAutoPtr<ITextureGL> pTextureGL(pTexture, IID_TextureGL);
+ auto GLHandle = pTextureGL->GetGLTextureHandle();
+ RefCntAutoPtr<ITexture> pAttachedTexture;
+ auto TmpTexDesc = SrcTexDesc;
+ TmpTexDesc.Width = 0;
+ TmpTexDesc.Height = 0;
+ TmpTexDesc.MipLevels = 0;
+ TmpTexDesc.Format = TEX_FORMAT_UNKNOWN;
+ pDeviceGL->CreateTextureFromGLHandle(GLHandle, TmpTexDesc, &pAttachedTexture);
+
+ const auto &TestTexDesc = pAttachedTexture->GetDesc();
+ VERIFY_EXPR(TestTexDesc == SrcTexDesc);
+ RefCntAutoPtr<ITextureGL> pAttachedTextureGL(pAttachedTexture, IID_TextureGL);
+ VERIFY_EXPR(pAttachedTextureGL->GetGLTextureHandle() == GLHandle);
+ VERIFY_EXPR(pAttachedTextureGL->GetBindTarget() == pTextureGL->GetBindTarget());
+ VERIFY_EXPR( reinterpret_cast<size_t>(pAttachedTextureGL->GetNativeHandle()) == GLHandle);
+#endif
+}
+
+void TestCreateObjFromNativeResGL::CreateBuffer(Diligent::IBuffer *pBuffer)
+{
+#if PLATFORM_WIN32 || PLATFORM_LINUX || PLATFORM_ANDROID
+ RefCntAutoPtr<IRenderDeviceGL> pDeviceGL(m_pDevice, IID_RenderDeviceGL);
+ const auto &SrcBuffDesc = pBuffer->GetDesc();
+ RefCntAutoPtr<IBufferGL> pBufferGL(pBuffer, IID_BufferGL);
+ auto GLBufferHandle = pBufferGL->GetGLBufferHandle();
+
+ RefCntAutoPtr<IBuffer> pBufferFromNativeGLHandle;
+ pDeviceGL->CreateBufferFromGLHandle(GLBufferHandle, SrcBuffDesc, &pBufferFromNativeGLHandle);
+
+ const auto &TestBufferDesc = pBufferFromNativeGLHandle->GetDesc();
+ VERIFY_EXPR(TestBufferDesc == SrcBuffDesc);
+
+ RefCntAutoPtr<IBufferGL> pTestBufferGL(pBufferFromNativeGLHandle, IID_BufferGL);
+ VERIFY_EXPR(pTestBufferGL->GetGLBufferHandle() == GLBufferHandle);
+ VERIFY_EXPR( reinterpret_cast<size_t>(pTestBufferGL->GetNativeHandle()) == GLBufferHandle);
+#endif
+}
diff --git a/Tests/TestApp/src/TestDepthStencilState.cpp b/Tests/TestApp/src/TestDepthStencilState.cpp
new file mode 100644
index 0000000..8ddb00c
--- /dev/null
+++ b/Tests/TestApp/src/TestDepthStencilState.cpp
@@ -0,0 +1,161 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "TestDepthStencilState.h"
+#include "ConvenienceFunctions.h"
+
+using namespace Diligent;
+
+void TestDepthStencilState::CreateTestDSS( DepthStencilStateDesc &DSSDesc )
+{
+ RefCntAutoPtr<IPipelineState> pPSO;
+ m_pDevice->CreatePipelineState( m_PSODesc, &pPSO );
+ m_pDeviceContext->SetPipelineState( pPSO );
+#if 0
+ DSSDesc.Name = "TestDSS2";
+ m_pDevice->CreateDepthStencilState( DSSDesc, &pDSState2 );
+ assert( pDSState == pDSState2 );
+ m_pDeviceContext->SetDepthStencilState( pDSState );
+ m_pDeviceContext->SetDepthStencilState( pDSState2 );
+ m_pDeviceContext->SetDepthStencilState( pDSState2, 2 );
+#endif
+}
+
+TestDepthStencilState::TestDepthStencilState( IRenderDevice *pDevice, IDeviceContext *pContext ) :
+ TestPipelineStateBase(pDevice),
+ m_pDeviceContext(pContext)
+{
+ DepthStencilStateDesc &DSSDesc = m_PSODesc.GraphicsPipeline.DepthStencilDesc;
+
+ DSSDesc.DepthEnable = False;
+ DSSDesc.DepthWriteEnable = False;
+ CreateTestDSS( DSSDesc );
+
+ DSSDesc.DepthEnable = True;
+ CreateTestDSS( DSSDesc );
+
+ DSSDesc.DepthWriteEnable = True;
+ CreateTestDSS( DSSDesc );
+
+ for( auto CmpFunc = COMPARISON_FUNC_UNKNOWN + 1; CmpFunc < COMPARISON_FUNC_NUM_FUNCTIONS; ++CmpFunc )
+ {
+ DSSDesc.DepthFunc = static_cast<COMPARISON_FUNCTION>(CmpFunc);
+ CreateTestDSS( DSSDesc );
+ }
+
+ DSSDesc.StencilEnable = True;
+ CreateTestDSS( DSSDesc );
+
+ DSSDesc.StencilReadMask = 0xA9;
+ CreateTestDSS( DSSDesc );
+
+ DSSDesc.StencilWriteMask = 0xB8;
+ CreateTestDSS( DSSDesc );
+
+ for( int Face = 0; Face < 2; ++Face )
+ {
+ auto &FaceOp = Face == 0 ? DSSDesc.FrontFace : DSSDesc.BackFace;
+ for( auto StOp = STENCIL_OP_UNDEFINED + 1; StOp < STENCIL_OP_NUM_OPS; ++StOp )
+ {
+ FaceOp.StencilFailOp = static_cast<STENCIL_OP>(StOp);
+ CreateTestDSS( DSSDesc );
+ }
+
+ for( auto StOp = STENCIL_OP_UNDEFINED + 1; StOp < STENCIL_OP_NUM_OPS; ++StOp )
+ {
+ FaceOp.StencilDepthFailOp = static_cast<STENCIL_OP>(StOp);
+ CreateTestDSS( DSSDesc );
+ }
+
+ for( auto StOp = STENCIL_OP_UNDEFINED + 1; StOp < STENCIL_OP_NUM_OPS; ++StOp )
+ {
+ FaceOp.StencilPassOp = static_cast<STENCIL_OP>(StOp);
+ CreateTestDSS( DSSDesc );
+ }
+
+ for( auto CmpFunc = COMPARISON_FUNC_UNKNOWN + 1; CmpFunc < COMPARISON_FUNC_NUM_FUNCTIONS; ++CmpFunc )
+ {
+ FaceOp.StencilFunc = static_cast<COMPARISON_FUNCTION>(CmpFunc);
+ CreateTestDSS( DSSDesc );
+ }
+ }
+
+ auto pScript = CreateRenderScriptFromFile( "DepthStencilStateTest.lua", pDevice, pContext, [&]( Diligent::ScriptParser *pScriptParser )
+ {
+ DSSDesc = DepthStencilStateDesc();
+ DSSDesc.DepthEnable = True;
+ DSSDesc.DepthWriteEnable = True;
+ DSSDesc.DepthFunc = COMPARISON_FUNC_NEVER;
+ DSSDesc.StencilEnable = True;
+ DSSDesc.StencilReadMask = 0xFA;
+ DSSDesc.StencilWriteMask = 0xFF;
+
+ DSSDesc.FrontFace.StencilFailOp = STENCIL_OP_DECR_SAT;
+ DSSDesc.FrontFace.StencilDepthFailOp = STENCIL_OP_DECR_WRAP;
+ DSSDesc.FrontFace.StencilPassOp = STENCIL_OP_INCR_WRAP;
+ DSSDesc.FrontFace.StencilFunc = COMPARISON_FUNC_NOT_EQUAL;
+
+ DSSDesc.BackFace.StencilFailOp = STENCIL_OP_INVERT;
+ DSSDesc.BackFace.StencilDepthFailOp = STENCIL_OP_REPLACE;
+ DSSDesc.BackFace.StencilPassOp = STENCIL_OP_INCR_SAT;
+ DSSDesc.BackFace.StencilFunc = COMPARISON_FUNC_EQUAL;
+ RefCntAutoPtr<IPipelineState> pPSO;
+ pDevice->CreatePipelineState( m_PSODesc, &pPSO );
+ pScriptParser->SetGlobalVariable( "TestGlobalPSO", pPSO );
+ }
+ );
+
+ {
+ RefCntAutoPtr<IPipelineState> pPSOFromScript, pDSStateFromScript2;
+ pScript->GetPipelineStateByName( "TestPSO", &pPSOFromScript);
+ //pScript->GetDepthStencilStateByName( "TestDSS2", &pDSStateFromScript2 );
+ //assert( pDSStateFromScript == pDSStateFromScript2 );
+ const auto &DSSDesc = pPSOFromScript->GetDesc().GraphicsPipeline.DepthStencilDesc;
+
+ assert( DSSDesc.DepthEnable == True );
+ assert( DSSDesc.DepthWriteEnable == True );
+ assert( DSSDesc.DepthFunc == COMPARISON_FUNC_LESS );
+ assert( DSSDesc.StencilEnable == True );
+ assert( DSSDesc.StencilReadMask == 0xF8 );
+ assert( DSSDesc.StencilWriteMask == 0xF1 );
+ assert( DSSDesc.FrontFace.StencilFailOp == STENCIL_OP_KEEP );
+ assert( DSSDesc.FrontFace.StencilDepthFailOp == STENCIL_OP_ZERO );
+ assert( DSSDesc.FrontFace.StencilPassOp == STENCIL_OP_REPLACE );
+ assert( DSSDesc.FrontFace.StencilFunc == COMPARISON_FUNC_EQUAL );
+ assert( DSSDesc.BackFace.StencilFailOp == STENCIL_OP_INCR_SAT );
+ assert( DSSDesc.BackFace.StencilDepthFailOp == STENCIL_OP_DECR_SAT );
+ assert( DSSDesc.BackFace.StencilPassOp == STENCIL_OP_INVERT );
+ assert( DSSDesc.BackFace.StencilFunc == COMPARISON_FUNC_NOT_EQUAL );
+ }
+
+ {
+ m_PSODesc.GraphicsPipeline.DepthStencilDesc = DepthStencilStateDesc();
+ RefCntAutoPtr<IPipelineState> pPSO;
+ m_pDevice->CreatePipelineState( m_PSODesc, &pPSO );
+ pScript->Run( m_pDeviceContext, "TestDSSDesc", pPSO );
+ }
+}
diff --git a/Tests/TestApp/src/TestDrawCommands.cpp b/Tests/TestApp/src/TestDrawCommands.cpp
new file mode 100644
index 0000000..d2f8841
--- /dev/null
+++ b/Tests/TestApp/src/TestDrawCommands.cpp
@@ -0,0 +1,964 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "TestDrawCommands.h"
+#include "MapHelper.h"
+#include "BasicShaderSourceStreamFactory.h"
+
+using namespace Diligent;
+
+void TestDrawCommands::Init( IRenderDevice *pDevice, IDeviceContext *pDeviceContext, float fMinXCoord, float fMinYCoord, float fXExtent, float fYExtent )
+{
+ m_pRenderDevice = pDevice;
+ m_pDeviceContext = pDeviceContext;
+
+ auto DevType = m_pRenderDevice->GetDeviceCaps().DevType;
+ bool bUseOpenGL = DevType == DeviceType::OpenGL || DevType == DeviceType::OpenGLES;
+
+ std::vector<float> VertexData;
+ std::vector<float> VertexData2;
+ std::vector<Uint32> IndexData;
+ std::vector<float> InstanceData;
+ Uint32 Ind = 0;
+ for( int iRow = 0; iRow < TriGridSize; ++iRow )
+ for( int iCol = 0; iCol < TriGridSize; ++iCol )
+ {
+ float fTriCenterX = (((float)iCol + 0.5f) / (float)TriGridSize) * fXExtent + fMinXCoord;
+ float fTriCenterY = (((float)iRow + 0.5f) / (float)TriGridSize) * fYExtent + fMinYCoord;
+ float fTriSizeX = fXExtent / (float)TriGridSize * 0.9f;
+ float fTriSizeY = fYExtent / (float)TriGridSize * 0.9f;
+ Define2DVertex( VertexData, fTriCenterX - 0.5f*fTriSizeX, fTriCenterY - 0.5f*fTriSizeY, 1, 0, 0 );
+ Define2DVertex( VertexData, fTriCenterX + 0.5f*fTriSizeX, fTriCenterY - 0.5f*fTriSizeY, 0, 1, 0 );
+ Define2DVertex( VertexData, fTriCenterX + 0.0f*fTriSizeX, fTriCenterY + 0.5f*fTriSizeY, 0, 0, 1 );
+
+ Define2DVertex( VertexData2, fTriCenterX - 0.5f*fTriSizeX, fTriCenterY - 0.5f*fTriSizeY, 1, 1, 0 );
+ Define2DVertex( VertexData2, fTriCenterX + 0.5f*fTriSizeX, fTriCenterY - 0.5f*fTriSizeY, 0, 1, 1 );
+ Define2DVertex( VertexData2, fTriCenterX + 0.0f*fTriSizeX, fTriCenterY + 0.5f*fTriSizeY, 1, 0, 1 );
+
+ InstanceData.push_back( (float)iCol / (float)TriGridSize * fXExtent );
+ InstanceData.push_back( (float)iRow / (float)TriGridSize * fYExtent );
+
+ IndexData.push_back( Ind++ );
+ IndexData.push_back( Ind++ );
+ IndexData.push_back( Ind++ );
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.uiSizeInBytes = (Uint32)VertexData.size()*sizeof( float );
+ BuffDesc.BindFlags = BIND_VERTEX_BUFFER;
+ BuffDesc.Usage = USAGE_STATIC;
+ Diligent::BufferData BuffData;
+ BuffData.pData = VertexData.data();
+ BuffData.DataSize = (Uint32)VertexData.size()*sizeof( float );
+ m_pRenderDevice->CreateBuffer( BuffDesc, BuffData, &m_pVertexBuff );
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.uiSizeInBytes = (Uint32)VertexData2.size()*sizeof( float );
+ BuffDesc.BindFlags = BIND_VERTEX_BUFFER;
+ BuffDesc.Usage = USAGE_STATIC;
+ Diligent::BufferData BuffData;
+ BuffData.pData = VertexData2.data();
+ BuffData.DataSize = (Uint32)VertexData2.size()*sizeof( float );
+ m_pRenderDevice->CreateBuffer( BuffDesc, BuffData, &m_pVertexBuff2 );
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.uiSizeInBytes = (Uint32)IndexData.size() * sizeof( Uint32 );
+ BuffDesc.BindFlags = BIND_INDEX_BUFFER;
+ BuffDesc.Usage = USAGE_STATIC;
+ Diligent::BufferData BuffData;
+ BuffData.pData = IndexData.data();
+ BuffData.DataSize = BuffDesc.uiSizeInBytes;
+ m_pRenderDevice->CreateBuffer( BuffDesc, BuffData, &m_pIndexBuff );
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.uiSizeInBytes = (Uint32)InstanceData.size() * sizeof( float );
+ BuffDesc.BindFlags = BIND_VERTEX_BUFFER;
+ BuffDesc.Usage = USAGE_STATIC;
+ Diligent::BufferData BuffData;
+ BuffData.pData = InstanceData.data();
+ BuffData.DataSize = BuffDesc.uiSizeInBytes;
+ m_pRenderDevice->CreateBuffer( BuffDesc, BuffData, &m_pInstanceData );
+ }
+
+ if( m_pRenderDevice->GetDeviceCaps().bIndirectRenderingSupported )
+ {
+ //typedef struct {
+ // GLuint count;
+ // GLuint instanceCount;
+ // GLuint first;
+ // GLuint baseInstance;
+ //} DrawArraysIndirectCommand;
+
+ Uint32 IndirectDrawArgs[] = { 3, 2, 0, 0 };
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.uiSizeInBytes = sizeof( IndirectDrawArgs );
+ // A buffer cannot be created if no bind flags set. We thus have to set this dummy BIND_VERTEX_BUFFER flag
+ // to be able to create the buffer
+ BuffDesc.BindFlags = BIND_INDIRECT_DRAW_ARGS | BIND_VERTEX_BUFFER;
+ BuffDesc.Usage = USAGE_DYNAMIC;
+ BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ m_pRenderDevice->CreateBuffer( BuffDesc, BufferData(), &m_pIndirectDrawArgs );
+ }
+
+ {
+ //typedef struct {
+ // GLuint count;
+ // GLuint instanceCount;
+ // GLuint firstIndex;
+ // GLuint baseVertex;
+ // GLuint baseInstance;
+ //} DrawElementsIndirectCommand;
+
+ Uint32 IndirectDrawArgs[] = { 3, 2, 0, 0, 0 };
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.uiSizeInBytes = sizeof( IndirectDrawArgs );
+ // A buffer cannot be created if no bind flags set. We thus have to set this dummy flag
+ // to be able to create the buffer
+ BuffDesc.BindFlags = BIND_INDIRECT_DRAW_ARGS | BIND_VERTEX_BUFFER;
+ BuffDesc.Usage = USAGE_DYNAMIC;
+ BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ m_pRenderDevice->CreateBuffer( BuffDesc, BufferData(), &m_pIndexedIndirectDrawArgs );
+ }
+
+
+ ShaderCreationAttribs CreationAttrs;
+ BasicShaderSourceStreamFactory BasicSSSFactory;
+ CreationAttrs.pShaderSourceStreamFactory = &BasicSSSFactory;
+ CreationAttrs.Desc.TargetProfile = bUseOpenGL ? SHADER_PROFILE_GL_4_2 : SHADER_PROFILE_DX_5_0;
+
+ RefCntAutoPtr<Diligent::IShader> pVS, pVSInst, pPS;
+ {
+ CreationAttrs.FilePath = bUseOpenGL ? "Shaders\\minimalGL.vsh" : "Shaders\\minimalDX.vsh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ m_pRenderDevice->CreateShader( CreationAttrs, &pVS );
+ }
+
+ {
+ CreationAttrs.FilePath = bUseOpenGL ? "Shaders\\minimalInstGL.vsh" : "Shaders\\minimalInstDX.vsh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ m_pRenderDevice->CreateShader( CreationAttrs, &pVSInst );
+ }
+
+ {
+ CreationAttrs.FilePath = bUseOpenGL ? "Shaders\\minimalGL.psh" : "Shaders\\minimalDX.psh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_PIXEL;
+ m_pRenderDevice->CreateShader( CreationAttrs, &pPS );
+ }
+
+ PipelineStateDesc PSODesc;
+ PSODesc.GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
+ PSODesc.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE;
+ PSODesc.GraphicsPipeline.BlendDesc.IndependentBlendEnable = False;
+ PSODesc.GraphicsPipeline.BlendDesc.RenderTargets[0].BlendEnable = False;
+ PSODesc.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM_SRGB;
+ PSODesc.GraphicsPipeline.NumRenderTargets = 1;
+ PSODesc.GraphicsPipeline.pPS = pPS;
+
+ BlendStateDesc &BSDesc = PSODesc.GraphicsPipeline.BlendDesc;
+ BSDesc.IndependentBlendEnable = False;
+ BSDesc.RenderTargets[0].BlendEnable = True;
+ BSDesc.RenderTargets[0].SrcBlend = BLEND_FACTOR_ONE;
+ BSDesc.RenderTargets[0].DestBlend = BLEND_FACTOR_ONE;
+ BSDesc.RenderTargets[0].BlendOp = BLEND_OPERATION_ADD;
+ BSDesc.RenderTargets[0].SrcBlendAlpha = BLEND_FACTOR_ONE;
+ BSDesc.RenderTargets[0].DestBlendAlpha = BLEND_FACTOR_ZERO;
+ BSDesc.RenderTargets[0].BlendOpAlpha = BLEND_OPERATION_ADD;
+
+ {
+ PSODesc.GraphicsPipeline.pVS = pVS;
+
+ InputLayoutDesc LayoutDesc;
+ LayoutElement Elems[] =
+ {
+ LayoutElement( 0, 0, 3, Diligent::VT_FLOAT32, false, 0 ),
+ LayoutElement( 1, 0, 3, Diligent::VT_FLOAT32, false, sizeof( float ) * 3 )
+ };
+ PSODesc.GraphicsPipeline.InputLayout.LayoutElements = Elems;
+ PSODesc.GraphicsPipeline.InputLayout.NumElements = _countof( Elems );
+ m_pRenderDevice->CreatePipelineState( PSODesc, &m_pPSO );
+ }
+
+ {
+ PSODesc.GraphicsPipeline.pVS = pVSInst;
+
+ InputLayoutDesc LayoutDesc;
+ LayoutElement Elems[] =
+ {
+ LayoutElement( 0, 0, 3, Diligent::VT_FLOAT32, false, 0 ),
+ LayoutElement( 1, 0, 3, Diligent::VT_FLOAT32, false, sizeof( float ) * 3 ),
+ LayoutElement( 2, 1, 2, Diligent::VT_FLOAT32, false, 0, LayoutElement::FREQUENCY_PER_INSTANCE )
+ };
+ PSODesc.GraphicsPipeline.InputLayout.LayoutElements = Elems;
+ PSODesc.GraphicsPipeline.InputLayout.NumElements = _countof( Elems );
+ m_pRenderDevice->CreatePipelineState( PSODesc, &m_pPSOInst );
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ float UniformData[16] = { 1, 1, 1, 1 };
+ BuffDesc.uiSizeInBytes = sizeof( UniformData );
+ BuffDesc.BindFlags = BIND_UNIFORM_BUFFER;
+ BuffDesc.Usage = USAGE_DEFAULT;
+ BuffDesc.CPUAccessFlags = 0;
+ Diligent::BufferData BuffData;
+ BuffData.pData = UniformData;
+ BuffData.DataSize = sizeof( UniformData );
+ RefCntAutoPtr<IBuffer> pUniformBuff3, pUniformBuff4;
+ BuffDesc.Name = "Test Constant Buffer 3";
+ m_pRenderDevice->CreateBuffer( BuffDesc, BuffData, &pUniformBuff3 );
+ BuffDesc.Name = "Test Constant Buffer 4";
+ m_pRenderDevice->CreateBuffer( BuffDesc, BuffData, &pUniformBuff4 );
+
+ Diligent::ResourceMappingDesc ResMappingDesc;
+ ResourceMappingEntry pEtries[] = { { "cbTestBlock3", pUniformBuff3 }, { "cbTestBlock4", pUniformBuff4 }, { nullptr, nullptr } };
+ ResMappingDesc.pEntries = pEtries;
+ m_pRenderDevice->CreateResourceMapping( ResMappingDesc, &m_pResMapping );
+ }
+
+ pVS->BindResources(m_pResMapping, BIND_SHADER_RESOURCES_ALL_RESOLVED);
+ pVSInst->BindResources(m_pResMapping, BIND_SHADER_RESOURCES_ALL_RESOLVED);
+ pPS->BindResources(m_pResMapping, BIND_SHADER_RESOURCES_ALL_RESOLVED);
+}
+
+void TestDrawCommands::Draw()
+{
+ m_pDeviceContext->SetPipelineState(m_pPSO);
+ m_pDeviceContext->CommitShaderResources(nullptr, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES);
+
+ IBuffer *pBuffs[2] = {m_pVertexBuff, m_pInstanceData};
+ Uint32 Strides[] = {sizeof(float)*6, sizeof(float)*2};
+ Uint32 Offsets[] = {0, 0};
+ m_pDeviceContext->SetVertexBuffers( 0, 1, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET | BIND_SHADER_RESOURCES_ALL_RESOLVED );
+
+ Uint32 NumTestTrianglesInRow[TriGridSize] = { 0 };
+
+
+ // 1ST ROW: simple non-indexed drawing (glDrawArrays/Draw)
+
+ // 0,1: basic drawing
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumVertices = 2*3; // Draw 2 triangles
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 2,3: test StartVertex
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.StartVertexLocation = 2*3;
+ DrawAttrs.NumVertices = 2*3; // Draw 2 triangles
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 4,5: test buffer offset
+ Offsets[0] = 4*3*6*sizeof(float);
+ m_pDeviceContext->SetVertexBuffers(0, 1, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumVertices = 2*3; // Draw 2 triangles
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 6,7: test buffer offset & StartVertex
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.StartVertexLocation = 2*3;
+ DrawAttrs.NumVertices = 2*3; // Draw 2 triangles
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 8,9: test strides
+ Strides[0] *= 2;
+ m_pDeviceContext->SetVertexBuffers(0, 1, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.StartVertexLocation = 4*3/2; // Stride is 2x
+ DrawAttrs.NumVertices = 2*3; // Draw 2 triangles
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ NumTestTrianglesInRow[0] = 12;
+
+
+
+
+ // 2ND ROW: simple indexed rendering (glDrawElements/DrawIndexed)
+
+ Offsets[0] = 1*16*3 * 6*sizeof(float);
+ Strides[0] = 6*sizeof(float);
+ m_pDeviceContext->SetVertexBuffers(0, 1, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ m_pDeviceContext->SetIndexBuffer(m_pIndexBuff, 0);
+
+ // 0,1
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 2*3; // Draw 2 triangles
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 2,3: test index buffer offset
+ m_pDeviceContext->SetIndexBuffer( m_pIndexBuff, 2 * 3 * sizeof( Uint32 ) );
+
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 2*3; // Draw 2 triangles
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ NumTestTrianglesInRow[1] = 4;
+
+
+
+ // 3RD ROW: indexed rendering with BaseVertex (glDrawElementsBaseVertex/DrawIndexed)
+ Offsets[0] = (2*16*3 - 10) * 6*sizeof(float);
+ Strides[0] = 6*sizeof(float);
+ m_pDeviceContext->SetVertexBuffers(0, 1, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ m_pDeviceContext->SetIndexBuffer(m_pIndexBuff, 0);
+
+ // 0,1
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 2*3; // Draw 2 triangles
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ DrawAttrs.BaseVertex = 10;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 2,3: index buffer offset & Base Vertex
+ m_pDeviceContext->SetIndexBuffer( m_pIndexBuff, 2 * 3 * sizeof( Uint32 ) );
+
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 2*3; // Draw 2 triangles
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ DrawAttrs.BaseVertex = 10;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+ NumTestTrianglesInRow[2] = 4;
+
+
+ // 4TH ROW: Instanced non-indexed rendering (glDrawArraysInstanced/DrawInstanced)
+
+ m_pDeviceContext->SetPipelineState(m_pPSOInst);
+ m_pDeviceContext->TransitionShaderResources(m_pPSOInst, nullptr);
+ m_pDeviceContext->CommitShaderResources(nullptr, 0);
+
+ Offsets[0] = 3*16*3 * 6*sizeof(float);
+ Strides[0] = 6*sizeof(float);
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+
+ // 0,1
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumVertices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 2,3: Test offset in instance buffer
+ Offsets[1] = 2* Strides[1];
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumVertices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 4,5: test start vertex index
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumVertices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.StartVertexLocation = 2*3;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+ NumTestTrianglesInRow[3] = 6;
+
+
+
+
+ // 5TH ROW: instanced rendering with base instance (glDrawArraysInstancedBaseInstance/DrawInstanced)
+ Offsets[0] = 4*16*3 * 6*sizeof(float);
+ Strides[0] = 6*sizeof(float);
+ Offsets[1] = 0;
+ Strides[1] = 2*sizeof(float);
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ m_pDeviceContext->SetIndexBuffer(m_pIndexBuff, 0);
+ // 0,1
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.FirstInstanceLocation = 0;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 2,3
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.FirstInstanceLocation = 2;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 4,5: test vertex buffer offset
+ Offsets[0] += 2*3 * Strides[0];
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.FirstInstanceLocation = 2;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 6,7: test instance buffer offset
+ Offsets[1] += 2 * Strides[1];
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.FirstInstanceLocation = 2;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+ NumTestTrianglesInRow[4] = 8;
+
+
+
+ // 6TH ROW: instanced indexed rendering (glDrawElementsInstanced/DrawIndexedInstanced)
+
+ Offsets[0] = 5*16*3 * 6*sizeof(float);
+ Strides[0] = 6*sizeof(float);
+ Offsets[1] = 0;
+ Strides[1] = 2*sizeof(float);
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ m_pDeviceContext->SetIndexBuffer(m_pIndexBuff, 0);
+ // 0,1
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 2,3: test index buffer offset
+ m_pDeviceContext->SetIndexBuffer( m_pIndexBuff, 2 * 3 * sizeof( Uint32 ) );
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 4,5: test vertex buffer offset
+ Offsets[0] += 2*3 * Strides[0];
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 6,7: test instance buffer offset
+ Offsets[1] += 2 * Strides[1];
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 8,9: test first index location
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.FirstIndexLocation = 2*3;
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+ NumTestTrianglesInRow[5] = 10;
+
+
+
+
+ // 7TH ROW: instanced indexed rendering with base instance (glDrawElementsInstancedBaseInstance/DrawInstanced)
+
+ Offsets[0] = 6*16*3 * 6*sizeof(float);
+ Strides[0] = 6*sizeof(float);
+ Offsets[1] = 0;
+ Strides[1] = 2*sizeof(float);
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ m_pDeviceContext->SetIndexBuffer(m_pIndexBuff, 0);
+ // 0,1
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+ // 2,3
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ DrawAttrs.FirstInstanceLocation = 2;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 4,5: test index buffer offset
+ m_pDeviceContext->SetIndexBuffer( m_pIndexBuff, 2 * 3 * sizeof( Uint32 ) );
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ DrawAttrs.FirstInstanceLocation = 2;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 6,7: test instance buffer offset
+ Offsets[1] += Strides[1] * 2;
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ DrawAttrs.FirstInstanceLocation = 2;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 8,9: test first index location
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ DrawAttrs.FirstInstanceLocation = 2;
+ DrawAttrs.FirstIndexLocation = 2*3;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+ NumTestTrianglesInRow[6] = 10;
+
+
+
+ // 8TH ROW: instanced indexed rendering with base vertex (glDrawElementsInstancedBaseVertex/DrawInstanced)
+
+ Offsets[0] = 7*16*3 * 6*sizeof(float);
+ Strides[0] = 6*sizeof(float);
+ Offsets[1] = 0;
+ Strides[1] = 2*sizeof(float);
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ m_pDeviceContext->SetIndexBuffer(m_pIndexBuff, 0);
+ // 0,1
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 2,3
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.BaseVertex = 2*3;
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 4,5: test index buffer offset
+ m_pDeviceContext->SetIndexBuffer( m_pIndexBuff, 2 * 3 * sizeof( Uint32 ) );
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.BaseVertex = 2*3;
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 6,7: test instance buffer offset
+ Offsets[1] += Strides[1] * 2;
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.BaseVertex = 2*3;
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 8,9: Test first index location
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.BaseVertex = 2*3;
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ DrawAttrs.FirstIndexLocation = 2*3;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+ NumTestTrianglesInRow[7] = 10;
+
+
+
+ // 9TH ROW: instanced indexed rendering with base vertex & base instance (glDrawElementsInstancedBaseVertexBaseInstance/DrawInstanced)
+
+ Offsets[0] = 8*16*3 * 6*sizeof(float);
+ Strides[0] = 6*sizeof(float);
+ Offsets[1] = 0;
+ Strides[1] = 2*sizeof(float);
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ m_pDeviceContext->SetIndexBuffer(m_pIndexBuff, 0);
+ // 0,1
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 2,3
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.BaseVertex = 3;
+ DrawAttrs.FirstInstanceLocation = 1;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 4,5: test index buffer offset
+ m_pDeviceContext->SetIndexBuffer( m_pIndexBuff, 2 * 3 * sizeof( Uint32 ) );
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.BaseVertex = 3;
+ DrawAttrs.FirstInstanceLocation = 1;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 6,7: test instance buffer offset
+ Offsets[1] += Strides[1] * 2;
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.BaseVertex = 3;
+ DrawAttrs.FirstInstanceLocation = 1;
+ DrawAttrs.IndexType = VT_UINT32;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 8,9: test first index location
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+ DrawAttrs.NumInstances = 2; // Draw 2 instances
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.BaseVertex = 3;
+ DrawAttrs.FirstInstanceLocation = 1;
+ DrawAttrs.IndexType = VT_UINT32;
+ DrawAttrs.FirstIndexLocation = 2*3;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+ NumTestTrianglesInRow[8] = 10;
+
+
+
+ if( m_pRenderDevice->GetDeviceCaps().bIndirectRenderingSupported )
+ {
+ // 10TH ROW: instanced non-indexed indirect rendering (glDrawArraysIndirect/DrawInstancedIndirect)
+
+ // Test indirect non-indexed drawing
+ Offsets[0] = 9*16*3 * 6*sizeof(float);
+ Strides[0] = 6*sizeof(float);
+ Offsets[1] = 0;
+ Strides[1] = 2*sizeof(float);
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+
+ // 0,1
+ {
+ MapHelper<Uint32, true> MappedData(m_pDeviceContext, m_pIndirectDrawArgs, MAP_WRITE, MAP_FLAG_DISCARD);
+ MappedData[0] = 3; // Vertex count
+ MappedData[1] = 2; // Num instances
+ MappedData[2] = 0; // Start vertex
+ MappedData[3] = 0; // Start instance
+ MappedData.Unmap();
+
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.IsIndirect = true;
+ DrawAttrs.pIndirectDrawAttribs = m_pIndirectDrawArgs;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 2,3: test first vertex location
+ {
+ MapHelper<Uint32, true> MappedData( m_pDeviceContext, m_pIndirectDrawArgs, MAP_WRITE, MAP_FLAG_DISCARD );
+ MappedData[0] = 3; // Vertex count
+ MappedData[1] = 2; // Num instances
+ MappedData[2] = 3*2; // Start vertex
+ MappedData[3] = 0; // Start instance
+ MappedData.Unmap();
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.IsIndirect = true;
+ DrawAttrs.pIndirectDrawAttribs = m_pIndirectDrawArgs;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 4,5: test first instance location
+ {
+ MapHelper<Uint32, true> MappedData( m_pDeviceContext, m_pIndirectDrawArgs, MAP_WRITE, MAP_FLAG_DISCARD );
+ MappedData[0] = 3; // Vertex count
+ MappedData[1] = 2; // Num instances
+ MappedData[2] = 3*2; // Start vertex
+ MappedData[3] = 2; // Start instance
+ MappedData.Unmap();
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.IsIndirect = true;
+ DrawAttrs.pIndirectDrawAttribs = m_pIndirectDrawArgs;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ NumTestTrianglesInRow[9] = 6;
+
+
+
+
+ // 11TH ROW: instanced indexed indirect rendering (glDrawElementsIndirect/DrawIndexedInstancedIndirect)
+
+ Offsets[0] = 10*16*3 * 6*sizeof(float);
+ Strides[0] = 6*sizeof(float);
+ Offsets[1] = 0;
+ Strides[1] = 2*sizeof(float);
+ m_pDeviceContext->SetVertexBuffers(0, 2, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+ m_pDeviceContext->SetIndexBuffer(m_pIndexBuff, 0);
+
+ // 0,1
+ {
+ MapHelper<Uint32> MappedData( m_pDeviceContext, m_pIndexedIndirectDrawArgs, MAP_WRITE, MAP_FLAG_DISCARD );
+ MappedData[0] = 3; // Num indices
+ MappedData[1] = 2; // Num instances
+ MappedData[2] = 0; // Start index
+ MappedData[3] = 0; // Base vertex
+ MappedData[4] = 0; // Start instance
+ MappedData.Unmap();
+
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.IsIndirect = true;
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ DrawAttrs.pIndirectDrawAttribs = m_pIndexedIndirectDrawArgs;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 2,3: test start index location
+ {
+ MapHelper<Uint32> MappedData( m_pDeviceContext, m_pIndexedIndirectDrawArgs, MAP_WRITE, MAP_FLAG_DISCARD );
+ MappedData[0] = 3; // Num indices
+ MappedData[1] = 2; // Num instances
+ MappedData[2] = 6; // Start index
+ MappedData[3] = 0; // Base vertex
+ MappedData[4] = 0; // Start instance
+ MappedData.Unmap();
+
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.IsIndirect = true;
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ DrawAttrs.pIndirectDrawAttribs = m_pIndexedIndirectDrawArgs;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 4,5: test base vertex
+ {
+ MapHelper<Uint32> MappedData( m_pDeviceContext, m_pIndexedIndirectDrawArgs, MAP_WRITE, MAP_FLAG_DISCARD );
+ MappedData[0] = 3; // Num indices
+ MappedData[1] = 2; // Num instances
+ MappedData[2] = 6; // Start index
+ MappedData[3] = 2*3;// Base vertex
+ MappedData[4] = 0; // Start instance
+ MappedData.Unmap();
+
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.IsIndirect = true;
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ DrawAttrs.pIndirectDrawAttribs = m_pIndexedIndirectDrawArgs;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+
+ // 6,7: test start instance
+ {
+ MapHelper<Uint32> MappedData( m_pDeviceContext, m_pIndexedIndirectDrawArgs, MAP_WRITE, MAP_FLAG_DISCARD );
+ MappedData[0] = 3; // Num indices
+ MappedData[1] = 2; // Num instances
+ MappedData[2] = 6; // Start index
+ MappedData[3] = 2*3;// Base vertex
+ MappedData[4] = 2; // Start instance
+ MappedData.Unmap();
+
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.IsIndirect = true;
+ DrawAttrs.IsIndexed = true;
+ DrawAttrs.IndexType = VT_UINT32;
+ DrawAttrs.pIndirectDrawAttribs = m_pIndexedIndirectDrawArgs;
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+ NumTestTrianglesInRow[10] = 8;
+ }
+
+ // Draw end triangles
+ Offsets[0] = 0;
+ Strides[0] = 6*sizeof(float);
+ pBuffs[0] = m_pVertexBuff2;
+ m_pDeviceContext->SetVertexBuffers(0, 1, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET);
+
+ m_pDeviceContext->SetPipelineState(m_pPSO);
+ m_pDeviceContext->CommitShaderResources(nullptr, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES);
+
+ {
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ DrawAttrs.NumIndices = 3; // Draw 1 triangle
+
+ for(int iRow=0; iRow < TriGridSize; ++iRow)
+ {
+ DrawAttrs.StartVertexLocation = 16*3*iRow + 3*(1+NumTestTrianglesInRow[iRow]);
+ m_pDeviceContext->Draw(DrawAttrs);
+ }
+ }
+
+ m_pDeviceContext->SetVertexBuffers( 0, 0, nullptr, 0, 0, SET_VERTEX_BUFFERS_FLAG_RESET );
+}
+
+
+void TestDrawCommands::Define2DVertex(std::vector<float> &VertexData, float fX, float fY, float fR, float fG, float fB)
+{
+ VertexData.push_back(fX);
+ VertexData.push_back(fY);
+ VertexData.push_back(0.5f);
+ VertexData.push_back(fR);
+ VertexData.push_back(fG);
+ VertexData.push_back(fB);
+}
diff --git a/Tests/TestApp/src/TestGeometryShader.cpp b/Tests/TestApp/src/TestGeometryShader.cpp
new file mode 100644
index 0000000..9492c93
--- /dev/null
+++ b/Tests/TestApp/src/TestGeometryShader.cpp
@@ -0,0 +1,86 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "TestGeometryShader.h"
+#include "MapHelper.h"
+#include "BasicShaderSourceStreamFactory.h"
+
+using namespace Diligent;
+
+void TestGeometryShader::Init( IRenderDevice *pDevice, IDeviceContext *pDeviceContext)
+{
+ m_pDeviceContext = pDeviceContext;
+
+ ShaderCreationAttribs CreationAttrs;
+ BasicShaderSourceStreamFactory BasicSSSFactory;
+ CreationAttrs.pShaderSourceStreamFactory = &BasicSSSFactory;
+ CreationAttrs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
+
+ RefCntAutoPtr<Diligent::IShader> pVS, pGS, pPS;
+ {
+ CreationAttrs.FilePath = "Shaders\\GSTestDX.vsh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ pDevice->CreateShader( CreationAttrs, &pVS );
+ }
+
+ {
+ CreationAttrs.FilePath = "Shaders\\GSTestDX.gsh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_GEOMETRY;
+ pDevice->CreateShader( CreationAttrs, &pGS );
+ }
+
+ {
+ CreationAttrs.FilePath = "Shaders\\GSTestDX.psh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_PIXEL;
+ pDevice->CreateShader( CreationAttrs, &pPS );
+ }
+
+ PipelineStateDesc PSODesc;
+ PSODesc.GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
+ PSODesc.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE;
+ PSODesc.GraphicsPipeline.BlendDesc.IndependentBlendEnable = False;
+ PSODesc.GraphicsPipeline.BlendDesc.RenderTargets[0].BlendEnable = False;
+ PSODesc.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM_SRGB;
+ PSODesc.GraphicsPipeline.NumRenderTargets = 1;
+ PSODesc.GraphicsPipeline.pPS = pPS;
+ PSODesc.GraphicsPipeline.pVS = pVS;
+ PSODesc.GraphicsPipeline.pGS = pGS;
+ PSODesc.GraphicsPipeline.PrimitiveTopologyType = PRIMITIVE_TOPOLOGY_TYPE_POINT;
+
+ pDevice->CreatePipelineState( PSODesc, &m_pPSO );
+}
+
+void TestGeometryShader::Draw()
+{
+ m_pDeviceContext->SetPipelineState(m_pPSO);
+ m_pDeviceContext->CommitShaderResources(nullptr, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES);
+
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_POINT_LIST;
+ DrawAttrs.NumVertices = 2; // Draw 2 triangles
+ m_pDeviceContext->Draw(DrawAttrs);
+}
diff --git a/Tests/TestApp/src/TestPipelineStateBase.cpp b/Tests/TestApp/src/TestPipelineStateBase.cpp
new file mode 100644
index 0000000..6de3d7a
--- /dev/null
+++ b/Tests/TestApp/src/TestPipelineStateBase.cpp
@@ -0,0 +1,65 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+#include "pch.h"
+#include "TestPipelineStateBase.h"
+
+using namespace Diligent;
+
+static const char g_ShaderSource[] =
+"void VSMain(out float4 pos : SV_POSITION) \n"
+"{ \n"
+" pos = float4(0,0,0,0); \n"
+"} \n"
+" \n"
+"void PSMain(out float4 col : SV_TARGET)\n"
+"{ \n"
+" col = float4(0,0,0,0); \n"
+"} \n"
+;
+
+TestPipelineStateBase::TestPipelineStateBase(Diligent::IRenderDevice *pDevice) :
+ m_pDevice(pDevice)
+{
+ ShaderCreationAttribs Attrs;
+ Attrs.Source = g_ShaderSource;
+ Attrs.EntryPoint = "VSMain";
+ Attrs.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ Attrs.Desc.Name = "TrivialVS";
+ Attrs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
+ m_pDevice->CreateShader(Attrs, &m_pTrivialVS);
+
+ Attrs.EntryPoint = "PSMain";
+ Attrs.Desc.ShaderType = SHADER_TYPE_PIXEL;
+ Attrs.Desc.Name = "TrivialPS";
+ m_pDevice->CreateShader(Attrs, &m_pTrivialPS);
+
+ m_PSODesc.GraphicsPipeline.pVS = m_pTrivialVS;
+ m_PSODesc.GraphicsPipeline.pPS = m_pTrivialPS;
+ m_PSODesc.GraphicsPipeline.PrimitiveTopologyType = PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
+ m_PSODesc.GraphicsPipeline.NumRenderTargets = 1;
+ m_PSODesc.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM;
+ m_PSODesc.GraphicsPipeline.DSVFormat = TEX_FORMAT_D32_FLOAT;
+}
diff --git a/Tests/TestApp/src/TestRasterizerState.cpp b/Tests/TestApp/src/TestRasterizerState.cpp
new file mode 100644
index 0000000..add2713
--- /dev/null
+++ b/Tests/TestApp/src/TestRasterizerState.cpp
@@ -0,0 +1,132 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "TestRasterizerState.h"
+#include "ConvenienceFunctions.h"
+
+using namespace Diligent;
+
+void TestRasterizerState::CreateTestRS()
+{
+ RefCntAutoPtr<IPipelineState> pPSO;
+ m_PSODesc.Name = "TestRS1";
+ m_pDevice->CreatePipelineState( m_PSODesc, &pPSO );
+ //RSDesc.Name = "TestRS2";
+ //m_pDevice->CreateRasterizerState( RSDesc, &pRS2 );
+ //assert( pRS == pRS2 );
+ m_pDeviceContext->SetPipelineState( pPSO );
+ //m_pDeviceContext->SetRasterizerState( pRS2 );
+}
+
+TestRasterizerState::TestRasterizerState( IRenderDevice *pDevice, IDeviceContext *pContext ) :
+ TestPipelineStateBase(pDevice),
+ m_pDeviceContext(pContext)
+{
+ RasterizerStateDesc &RSDesc = m_PSODesc.GraphicsPipeline.RasterizerDesc;
+ CreateTestRS( );
+
+ for( auto FillMode = FILL_MODE_UNDEFINED + 1; FillMode < FILL_MODE_NUM_MODES; ++FillMode )
+ {
+ RSDesc.FillMode = static_cast<FILL_MODE>(FillMode);
+ CreateTestRS();
+ }
+
+ for( auto CullMode = CULL_MODE_UNDEFINED + 1; CullMode < CULL_MODE_NUM_MODES; ++CullMode )
+ {
+ RSDesc.CullMode = static_cast<CULL_MODE>(CullMode);
+ CreateTestRS();
+ }
+
+ RSDesc.FrontCounterClockwise = !RSDesc.FrontCounterClockwise;
+ CreateTestRS();
+
+ RSDesc.DepthBias = 100;
+ CreateTestRS();
+
+ RSDesc.DepthBiasClamp = 1.f;
+ CreateTestRS();
+
+ RSDesc.SlopeScaledDepthBias = 2.f;
+ CreateTestRS();
+
+ RSDesc.DepthClipEnable = !RSDesc.DepthClipEnable;
+ CreateTestRS();
+
+#if 0
+ RSDesc.ScissorEnable = !RSDesc.ScissorEnable;
+ CreateTestRS( RSDesc );
+#endif
+
+ RSDesc.AntialiasedLineEnable = !RSDesc.AntialiasedLineEnable;
+ CreateTestRS();
+
+ auto pScript = CreateRenderScriptFromFile( "RasterizerStateTest.lua", pDevice, pContext, [&]( Diligent::ScriptParser *pScriptParser )
+ {
+ m_PSODesc.Name = "PSO-TestRS";
+ RSDesc = RasterizerStateDesc();
+ RSDesc.FillMode = FILL_MODE_WIREFRAME;
+ RSDesc.CullMode = CULL_MODE_FRONT;
+ RSDesc.FrontCounterClockwise = True;
+ RSDesc.DepthBias = 64;
+ RSDesc.DepthBiasClamp = 98.f;
+ RSDesc.SlopeScaledDepthBias = 12.5f;
+ RSDesc.DepthClipEnable = False;
+ RSDesc.ScissorEnable = False;
+ RSDesc.AntialiasedLineEnable = True;
+
+ RefCntAutoPtr<IPipelineState> pPSO;
+ pDevice->CreatePipelineState( m_PSODesc, &pPSO);
+ pScriptParser->SetGlobalVariable( "TestGlobalPSO", pPSO );
+ }
+ );
+
+ {
+ RefCntAutoPtr<IPipelineState> pPSOFromScript, pRSFromScript2;
+ pScript->GetPipelineStateByName( "TestRS_PSO", &pPSOFromScript);
+ //pScript->GetRasterizerStateByName( "TestRS2", &pRSFromScript2 );
+ const auto &PSODesc = pPSOFromScript->GetDesc();
+
+ const auto &RSDesc = PSODesc.GraphicsPipeline.RasterizerDesc;
+
+ assert( RSDesc.FillMode == FILL_MODE_WIREFRAME );
+ assert( RSDesc.CullMode == CULL_MODE_BACK );
+ assert( RSDesc.FrontCounterClockwise == True );
+ assert( RSDesc.DepthBias == 32 );
+ assert( RSDesc.DepthBiasClamp == 63.0 );
+ assert( RSDesc.SlopeScaledDepthBias == 31.25 );
+ assert( RSDesc.DepthClipEnable == True );
+ assert( RSDesc.ScissorEnable == False );
+ assert( RSDesc.AntialiasedLineEnable == True );
+ }
+
+ {
+ m_PSODesc.GraphicsPipeline.RasterizerDesc = RasterizerStateDesc();
+ RefCntAutoPtr<IPipelineState> pPSO;
+ m_pDevice->CreatePipelineState(m_PSODesc, &pPSO );
+ pScript->Run( m_pDeviceContext, "TestRSDescFunc", pPSO );
+ }
+}
diff --git a/Tests/TestApp/src/TestRenderTarget.cpp b/Tests/TestApp/src/TestRenderTarget.cpp
new file mode 100644
index 0000000..9f34203
--- /dev/null
+++ b/Tests/TestApp/src/TestRenderTarget.cpp
@@ -0,0 +1,54 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "TestRenderTarget.h"
+#include "GraphicsUtilities.h"
+#include "ConvenienceFunctions.h"
+
+using namespace Diligent;
+
+TestRenderTarget::TestRenderTarget()
+{
+}
+
+void TestRenderTarget::Init( IRenderDevice *pDevice, IDeviceContext *pDeviceContext, float fMinXCoord, float fMinYCoord, float fXExtent, float fYExtent )
+{
+ m_pRenderDevice = pDevice;
+ m_pDeviceContext = pDeviceContext;
+ m_pRenderScript = CreateRenderScriptFromFile( "TestRenderTargets.lua", pDevice, pDeviceContext, [&]( ScriptParser *pScriptParser )
+ {
+ pScriptParser->SetGlobalVariable( "MinX", fMinXCoord );
+ pScriptParser->SetGlobalVariable( "MinY", fMinYCoord );
+ pScriptParser->SetGlobalVariable( "XExt", fXExtent );
+ pScriptParser->SetGlobalVariable( "YExt", fYExtent );
+ } );
+}
+
+void TestRenderTarget::Draw()
+{
+ m_pRenderScript->Run( m_pDeviceContext, "Render" );
+}
diff --git a/Tests/TestApp/src/TestSamplerCreation.cpp b/Tests/TestApp/src/TestSamplerCreation.cpp
new file mode 100644
index 0000000..2b30e2a
--- /dev/null
+++ b/Tests/TestApp/src/TestSamplerCreation.cpp
@@ -0,0 +1,129 @@
+/* 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.
+ */
+
+#include "pch.h"
+#include "TestSamplerCreation.h"
+#include "RenderDevice.h"
+
+using namespace Diligent;
+
+const bool bIsGL43 = false;
+
+
+TestSamplerCreation::TestSamplerCreation(IRenderDevice *pDevice) :
+ m_pDevice(pDevice)
+{
+ // Test different filters
+ for(int Min = 0; Min < 2; ++Min)
+ for(int Mag = 0; Mag < 2; ++Mag)
+ for(int Mip = 0; Mip < 2; ++Mip)
+ {
+ SamplerDesc SamplerDesc;
+ SamplerDesc.MinFilter = Min ? FILTER_TYPE_LINEAR : FILTER_TYPE_POINT;
+ SamplerDesc.MagFilter = Mag ? FILTER_TYPE_LINEAR : FILTER_TYPE_POINT;
+ SamplerDesc.MipFilter = Mip ? FILTER_TYPE_LINEAR : FILTER_TYPE_POINT;
+ RefCntAutoPtr<ISampler> pSampler;
+ m_pDevice->CreateSampler(SamplerDesc, &pSampler);
+ }
+
+ {
+ SamplerDesc SamplerDesc;
+ SamplerDesc.MinFilter = FILTER_TYPE_ANISOTROPIC;
+ SamplerDesc.MagFilter = FILTER_TYPE_ANISOTROPIC;
+ SamplerDesc.MipFilter = FILTER_TYPE_ANISOTROPIC;
+ SamplerDesc.MaxAnisotropy = 4;
+ RefCntAutoPtr<ISampler> pSampler;
+ m_pDevice->CreateSampler(SamplerDesc, &pSampler);
+ }
+
+ for(int Min = 0; Min < 2; ++Min)
+ for(int Mag = 0; Mag < 2; ++Mag)
+ for(int Mip = 0; Mip < 2; ++Mip)
+ {
+ SamplerDesc SamplerDesc;
+ SamplerDesc.MinFilter = Min ? FILTER_TYPE_COMPARISON_LINEAR : FILTER_TYPE_COMPARISON_POINT;
+ SamplerDesc.MagFilter = Mag ? FILTER_TYPE_COMPARISON_LINEAR : FILTER_TYPE_COMPARISON_POINT;
+ SamplerDesc.MipFilter = Mip ? FILTER_TYPE_COMPARISON_LINEAR : FILTER_TYPE_COMPARISON_POINT;
+ RefCntAutoPtr<ISampler> pSampler;
+ m_pDevice->CreateSampler(SamplerDesc, &pSampler);
+ }
+
+ {
+ SamplerDesc SamplerDesc;
+ SamplerDesc.MinFilter = FILTER_TYPE_COMPARISON_ANISOTROPIC;
+ SamplerDesc.MagFilter = FILTER_TYPE_COMPARISON_ANISOTROPIC;
+ SamplerDesc.MipFilter = FILTER_TYPE_COMPARISON_ANISOTROPIC;
+ SamplerDesc.MaxAnisotropy = 4;
+ RefCntAutoPtr<ISampler> pSampler;
+ m_pDevice->CreateSampler(SamplerDesc, &pSampler);
+ }
+
+ // Test address modes
+ TEXTURE_ADDRESS_MODE AddrModes[] =
+ {
+ TEXTURE_ADDRESS_WRAP,
+ TEXTURE_ADDRESS_MIRROR,
+ TEXTURE_ADDRESS_CLAMP,
+ TEXTURE_ADDRESS_BORDER
+ //TEXTURE_ADDRESS_MIRROR_ONCE // This mode is not supported on Intel HW
+ };
+
+ for(int AddrMode = 0; AddrMode < _countof(AddrModes); ++AddrMode)
+ {
+ SamplerDesc SamplerDesc;
+ SamplerDesc.MinFilter = FILTER_TYPE_LINEAR;
+ SamplerDesc.MagFilter = FILTER_TYPE_LINEAR;
+ SamplerDesc.MipFilter = FILTER_TYPE_LINEAR;
+ SamplerDesc.AddressU = SamplerDesc.AddressV = SamplerDesc.AddressW = AddrModes[AddrMode];
+ RefCntAutoPtr<ISampler> pSampler;
+ m_pDevice->CreateSampler(SamplerDesc, &pSampler);
+ }
+
+ // Test comparison funcs
+ COMPARISON_FUNCTION CmpFuncs[] =
+ {
+ COMPARISON_FUNC_NEVER,
+ COMPARISON_FUNC_LESS,
+ COMPARISON_FUNC_EQUAL,
+ COMPARISON_FUNC_LESS_EQUAL,
+ COMPARISON_FUNC_GREATER,
+ COMPARISON_FUNC_NOT_EQUAL,
+ COMPARISON_FUNC_GREATER_EQUAL,
+ COMPARISON_FUNC_ALWAYS
+ };
+
+ for(int CmpFunc=0; CmpFunc < _countof(CmpFuncs); ++CmpFunc)
+ {
+ SamplerDesc SamplerDesc;
+ SamplerDesc.MinFilter = FILTER_TYPE_LINEAR;
+ SamplerDesc.MagFilter = FILTER_TYPE_LINEAR;
+ SamplerDesc.MipFilter = FILTER_TYPE_LINEAR;
+ SamplerDesc.ComparisonFunc = CmpFuncs[CmpFunc];
+ RefCntAutoPtr<ISampler> pSampler1, pSampler2;
+ SamplerDesc.Name = "Sam1";
+ m_pDevice->CreateSampler(SamplerDesc, &pSampler1);
+ SamplerDesc.Name = "Sam2";
+ m_pDevice->CreateSampler(SamplerDesc, &pSampler2);
+ assert(pSampler1 == pSampler2);
+ }
+}
diff --git a/Tests/TestApp/src/TestShaderResArrays.cpp b/Tests/TestApp/src/TestShaderResArrays.cpp
new file mode 100644
index 0000000..9b2b422
--- /dev/null
+++ b/Tests/TestApp/src/TestShaderResArrays.cpp
@@ -0,0 +1,190 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "TestShaderResArrays.h"
+#include "GraphicsUtilities.h"
+#include "BasicShaderSourceStreamFactory.h"
+#include "TestTexturing.h"
+
+using namespace Diligent;
+
+TestShaderResArrays::TestShaderResArrays(IRenderDevice *pDevice, IDeviceContext *pDeviceContext, bool bUseOpenGL, float fMinXCoord, float fMinYCoord, float fXExtent, float fYExtent)
+{
+ m_pRenderDevice = pDevice;
+ m_pDeviceContext = pDeviceContext;
+
+ ShaderCreationAttribs CreationAttrs;
+ BasicShaderSourceStreamFactory BasicSSSFactory;
+ CreationAttrs.pShaderSourceStreamFactory = &BasicSSSFactory;
+ CreationAttrs.Desc.TargetProfile = SHADER_PROFILE_DX_5_0;
+
+ RefCntAutoPtr<Diligent::IShader> pVS, pPS;
+ {
+ CreationAttrs.FilePath = "Shaders\\ShaderResArrayTest.vsh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ CreationAttrs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
+ m_pRenderDevice->CreateShader( CreationAttrs, &pVS );
+ }
+
+ {
+ CreationAttrs.FilePath = "Shaders\\ShaderResArrayTest.psh";
+
+ StaticSamplerDesc StaticSampler;
+ StaticSampler.Desc.MinFilter = FILTER_TYPE_LINEAR;
+ StaticSampler.Desc.MagFilter = FILTER_TYPE_LINEAR;
+ StaticSampler.Desc.MipFilter = FILTER_TYPE_LINEAR;
+ StaticSampler.TextureName = "g_tex2DTest";
+ CreationAttrs.Desc.NumStaticSamplers = 1;
+ CreationAttrs.Desc.StaticSamplers = &StaticSampler;
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_PIXEL;
+ CreationAttrs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
+ ShaderVariableDesc Vars[] =
+ {
+ {"g_tex2DTest", SHADER_VARIABLE_TYPE_MUTABLE},
+ {"g_tex2DTest2", SHADER_VARIABLE_TYPE_STATIC},
+ {"g_tex2D", SHADER_VARIABLE_TYPE_DYNAMIC}
+ };
+ CreationAttrs.Desc.VariableDesc = Vars;
+ CreationAttrs.Desc.NumVariables = _countof(Vars);
+
+ m_pRenderDevice->CreateShader( CreationAttrs, &pPS );
+ }
+
+ PipelineStateDesc PSODesc;
+ PSODesc.GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
+ PSODesc.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE;
+ PSODesc.GraphicsPipeline.BlendDesc.IndependentBlendEnable = False;
+ PSODesc.GraphicsPipeline.BlendDesc.RenderTargets[0].BlendEnable = False;
+ PSODesc.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM_SRGB;
+ PSODesc.GraphicsPipeline.NumRenderTargets = 1;
+ PSODesc.GraphicsPipeline.pVS = pVS;
+ PSODesc.GraphicsPipeline.pPS = pPS;
+
+ LayoutElement Elems[] =
+ {
+ LayoutElement( 0, 0, 3, Diligent::VT_FLOAT32, false, 0 ),
+ LayoutElement( 1, 0, 2, Diligent::VT_FLOAT32, false, sizeof( float ) * 3 )
+ };
+ PSODesc.GraphicsPipeline.InputLayout.LayoutElements = Elems;
+ PSODesc.GraphicsPipeline.InputLayout.NumElements = _countof( Elems );
+ pDevice->CreatePipelineState(PSODesc, &m_pPSO);
+ m_pPSO->CreateShaderResourceBinding(&m_pSRB);
+
+ float Vertices[] =
+ {
+ 0, 0, 0, 0,1,
+ 0, 1, 0, 0,0,
+ 1, 0, 0, 1,1,
+ 1, 1, 0, 1,0
+ };
+ for(int v=0; v < 4; ++v)
+ {
+ Vertices[v*5+0] = Vertices[v*5+0] * fXExtent + fMinXCoord;
+ Vertices[v*5+1] = Vertices[v*5+1] * fYExtent + fMinYCoord;
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.uiSizeInBytes = sizeof(Vertices);
+ BuffDesc.BindFlags = BIND_VERTEX_BUFFER;
+ BuffDesc.Usage = USAGE_STATIC;
+ Diligent::BufferData BuffData;
+ BuffData.pData = Vertices;
+ BuffData.DataSize = BuffDesc.uiSizeInBytes;
+ m_pRenderDevice->CreateBuffer(BuffDesc, BuffData, &m_pVertexBuff);
+ }
+
+ RefCntAutoPtr<ISampler> pSampler;
+ SamplerDesc SamDesc;
+ pDevice->CreateSampler(SamDesc, &pSampler);
+ for(auto t=0; t < _countof(m_pTextures); ++t)
+ {
+ TextureDesc TexDesc;
+ TexDesc.Type = RESOURCE_DIM_TEX_2D;
+ TexDesc.Width = 256;
+ TexDesc.Height = 256;
+ TexDesc.MipLevels = 8;
+ TexDesc.Usage = USAGE_STATIC;
+ TexDesc.Format = TEX_FORMAT_RGBA8_UNORM;
+ TexDesc.BindFlags = BIND_SHADER_RESOURCE;
+ TexDesc.Name = "Test Texture";
+
+ std::vector<Uint8> Data;
+ std::vector<TextureSubResData> SubResouces;
+ float ColorOffset[4] = {(float)t*0.13f, (float)t*0.21f, (float)t*0.29f, 0};
+ TestTexturing::GenerateTextureData(m_pRenderDevice, Data, SubResouces, TexDesc, ColorOffset);
+ TextureData TexData;
+ TexData.pSubResources = SubResouces.data();
+ TexData.NumSubresources = (Uint32)SubResouces.size();
+
+ m_pRenderDevice->CreateTexture( TexDesc, TexData, &m_pTextures[t] );
+ m_pTextures[t]->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)->SetSampler(pSampler);
+ }
+
+ ResourceMappingEntry ResMpEntries [] =
+ {
+ ResourceMappingEntry("g_tex2DTest", m_pTextures[0]->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE), 0),
+ ResourceMappingEntry("g_tex2DTest", m_pTextures[1]->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE), 1),
+ ResourceMappingEntry("g_tex2DTest", m_pTextures[2]->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE), 2),
+ ResourceMappingEntry("g_tex2DTest2", m_pTextures[5]->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE), 0),
+ ResourceMappingEntry("g_tex2D", m_pTextures[6]->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE), 0),
+ ResourceMappingEntry()
+ };
+
+ ResourceMappingDesc ResMappingDesc;
+ ResMappingDesc.pEntries = ResMpEntries;
+ RefCntAutoPtr<IResourceMapping> pResMapping;
+ m_pRenderDevice->CreateResourceMapping(ResMappingDesc, &pResMapping);
+
+ //pVS->BindResources(m_pResourceMapping, 0);
+ IDeviceObject *ppSRVs[] = {m_pTextures[3]->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)};
+ pPS->BindResources(pResMapping, BIND_SHADER_RESOURCES_RESET_BINDINGS | BIND_SHADER_RESOURCES_UPDATE_UNRESOLVED);
+ pPS->GetShaderVariable("g_tex2DTest2")->SetArray( ppSRVs, 1, 1);
+
+ m_pSRB->BindResources(SHADER_TYPE_PIXEL, pResMapping, BIND_SHADER_RESOURCES_RESET_BINDINGS | BIND_SHADER_RESOURCES_UPDATE_UNRESOLVED);
+ ppSRVs[0] = m_pTextures[4]->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE);
+ m_pSRB->GetVariable(SHADER_TYPE_PIXEL, "g_tex2DTest")->SetArray(ppSRVs, 3, 1);
+}
+
+void TestShaderResArrays::Draw()
+{
+ m_pDeviceContext->SetPipelineState(m_pPSO);
+ IDeviceObject *ppSRVs[] = {m_pTextures[7]->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)};
+ m_pSRB->GetVariable(SHADER_TYPE_PIXEL, "g_tex2D")->SetArray(ppSRVs, 1, 1);
+
+ m_pDeviceContext->CommitShaderResources(m_pSRB, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES);
+
+ IBuffer *pBuffs[] = {m_pVertexBuff};
+ Uint32 Strides[] = {sizeof(float)*5};
+ Uint32 Offsets[] = {0};
+ m_pDeviceContext->SetVertexBuffers( 0, 1, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET );
+
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ DrawAttrs.NumVertices = 4; // Draw quad
+ m_pDeviceContext->Draw( DrawAttrs );
+}
diff --git a/Tests/TestApp/src/TestTessellation.cpp b/Tests/TestApp/src/TestTessellation.cpp
new file mode 100644
index 0000000..ad2e334
--- /dev/null
+++ b/Tests/TestApp/src/TestTessellation.cpp
@@ -0,0 +1,128 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "TestTessellation.h"
+#include "MapHelper.h"
+#include "BasicShaderSourceStreamFactory.h"
+
+using namespace Diligent;
+
+void TestTessellation::Init( IRenderDevice *pDevice, IDeviceContext *pDeviceContext)
+{
+ m_pDeviceContext = pDeviceContext;
+
+ ShaderCreationAttribs CreationAttrs;
+ BasicShaderSourceStreamFactory BasicSSSFactory;
+ CreationAttrs.pShaderSourceStreamFactory = &BasicSSSFactory;
+ CreationAttrs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
+
+ RefCntAutoPtr<Diligent::IShader> pVS, pHS, pDS, pPS;
+ {
+ CreationAttrs.FilePath = "Shaders\\TessTestQuadDX.vsh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ pDevice->CreateShader( CreationAttrs, &pVS );
+ }
+
+ {
+ CreationAttrs.FilePath = "Shaders\\TessTestQuadDX.hsh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_HULL;
+ pDevice->CreateShader( CreationAttrs, &pHS );
+ }
+
+ {
+ CreationAttrs.FilePath = "Shaders\\TessTestQuadDX.dsh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_DOMAIN;
+ pDevice->CreateShader( CreationAttrs, &pDS );
+ }
+
+ {
+ CreationAttrs.FilePath = "Shaders\\GSTestDX.psh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_PIXEL;
+ pDevice->CreateShader( CreationAttrs, &pPS );
+ }
+
+ PipelineStateDesc PSODesc;
+ PSODesc.GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
+ PSODesc.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE;
+ PSODesc.GraphicsPipeline.RasterizerDesc.FillMode = FILL_MODE_WIREFRAME;
+ PSODesc.GraphicsPipeline.BlendDesc.IndependentBlendEnable = False;
+ PSODesc.GraphicsPipeline.BlendDesc.RenderTargets[0].BlendEnable = False;
+ PSODesc.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM_SRGB;
+ PSODesc.GraphicsPipeline.NumRenderTargets = 1;
+ PSODesc.GraphicsPipeline.pPS = pPS;
+ PSODesc.GraphicsPipeline.pVS = pVS;
+ PSODesc.GraphicsPipeline.pHS = pHS;
+ PSODesc.GraphicsPipeline.pDS = pDS;
+ PSODesc.GraphicsPipeline.PrimitiveTopologyType = PRIMITIVE_TOPOLOGY_TYPE_PATCH;
+
+ pDevice->CreatePipelineState( PSODesc, &m_pQuadPSO );
+
+
+ {
+ pVS.Release();
+ CreationAttrs.FilePath = "Shaders\\TessTestTriDX.vsh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ pDevice->CreateShader( CreationAttrs, &pVS );
+ }
+
+ {
+ pHS.Release();
+ CreationAttrs.FilePath = "Shaders\\TessTestTriDX.hsh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_HULL;
+ pDevice->CreateShader( CreationAttrs, &pHS );
+ }
+
+ {
+ pDS.Release();
+ CreationAttrs.FilePath = "Shaders\\TessTestTriDX.dsh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_DOMAIN;
+ pDevice->CreateShader( CreationAttrs, &pDS );
+ }
+
+ PSODesc.GraphicsPipeline.pPS = pPS;
+ PSODesc.GraphicsPipeline.pVS = pVS;
+ PSODesc.GraphicsPipeline.pHS = pHS;
+ PSODesc.GraphicsPipeline.pDS = pDS;
+
+ pDevice->CreatePipelineState( PSODesc, &m_pTriPSO );
+}
+
+void TestTessellation::Draw()
+{
+ m_pDeviceContext->SetPipelineState(m_pQuadPSO);
+ m_pDeviceContext->CommitShaderResources(nullptr, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES);
+
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST;
+ DrawAttrs.NumVertices = 2; // Draw 2 quad patches
+ m_pDeviceContext->Draw(DrawAttrs);
+
+ m_pDeviceContext->SetPipelineState(m_pTriPSO);
+ m_pDeviceContext->CommitShaderResources(nullptr, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES);
+ DrawAttrs.NumVertices = 1; // Draw 1 tri patch
+ m_pDeviceContext->Draw(DrawAttrs);
+}
diff --git a/Tests/TestApp/src/TestTextureCreation.cpp b/Tests/TestApp/src/TestTextureCreation.cpp
new file mode 100644
index 0000000..ab1967e
--- /dev/null
+++ b/Tests/TestApp/src/TestTextureCreation.cpp
@@ -0,0 +1,953 @@
+/* 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.
+ */
+
+#include "pch.h"
+#include "TestTextureCreation.h"
+#include "RenderDevice.h"
+#include "GraphicsUtilities.h"
+#include "Errors.h"
+#include "TestCreateObjFromNativeRes.h"
+
+#if D3D11_SUPPORTED
+#include "TestCreateObjFromNativeResD3D11.h"
+#endif
+
+#if D3D12_SUPPORTED
+#include "TestCreateObjFromNativeResD3D12.h"
+#endif
+
+#if OPENGL_SUPPORTED
+#include "TestCreateObjFromNativeResGL.h"
+#endif
+
+using namespace Diligent;
+
+class TextureCreationVerifier
+{
+public:
+ TextureCreationVerifier( IRenderDevice *pDevice, IDeviceContext *pContext ) :
+ m_pDevice(pDevice),
+ m_pDeviceContext(pContext),
+ m_TextureFormat(TEX_FORMAT_UNKNOWN),
+ m_BindFlags(0),
+ m_PixelSize(0),
+ m_bTestDataUpload(False)
+ {
+ auto DevType = m_pDevice->GetDeviceCaps().DevType;
+ switch (DevType)
+ {
+#if D3D11_SUPPORTED
+ case DeviceType::D3D11:
+ m_pTestCreateObjFromNativeRes.reset(new TestCreateObjFromNativeResD3D11(pDevice));
+ break;
+#endif
+
+#if D3D12_SUPPORTED
+ case DeviceType::D3D12:
+ m_pTestCreateObjFromNativeRes.reset(new TestCreateObjFromNativeResD3D12(pDevice));
+ break;
+#endif
+
+#if OPENGL_SUPPORTED
+ case DeviceType::OpenGL:
+ case DeviceType::OpenGLES:
+ m_pTestCreateObjFromNativeRes.reset(new TestCreateObjFromNativeResGL(pDevice));
+ break;
+#endif
+
+ default: UNEXPECTED("Unexpected device type");
+ }
+ }
+
+ void Test(TEXTURE_FORMAT TextureFormat,
+ Uint32 PixelSize,
+ Uint32 BindFlags,
+ Bool TestDataUpload)
+ {
+ m_TextureFormat = TextureFormat;
+ m_BindFlags = BindFlags;
+ m_PixelSize = PixelSize;
+ m_bTestDataUpload = TestDataUpload;
+
+ auto PixelFormatAttribs = m_pDevice->GetTextureFormatInfoExt(TextureFormat);
+
+ const auto &TexCaps = m_pDevice->GetDeviceCaps().TexCaps;
+ // Test texture 1D / texture 1D array
+ if( TexCaps.bTexture1DSupported )
+ {
+ if( PixelFormatAttribs.Tex1DFmt )
+ CreateTestTexture( RESOURCE_DIM_TEX_1D, 1 );
+ }
+ else
+ {
+ static bool FirstTime = true;
+ if( FirstTime )
+ {
+ LOG_WARNING_MESSAGE( "Texture 1D is not supported\n" );
+ FirstTime = false;
+ }
+ }
+
+ if( TexCaps.bTexture1DArraySupported )
+ {
+ if( PixelFormatAttribs.Tex1DFmt )
+ CreateTestTexture( RESOURCE_DIM_TEX_1D_ARRAY, 1 );
+ }
+ else
+ {
+ static bool FirstTime = true;
+ if( FirstTime )
+ {
+ LOG_WARNING_MESSAGE( "Texture 1D array is not supported\n" );
+ FirstTime = false;
+ }
+ }
+
+ // Test texture 2D / texture 2D array
+ CreateTestTexture(RESOURCE_DIM_TEX_2D, 1);
+ CreateTestTexture(RESOURCE_DIM_TEX_2D, 1);
+ CreateTestTexture(RESOURCE_DIM_TEX_2D_ARRAY, 1);
+ CreateTestTexture(RESOURCE_DIM_TEX_2D_ARRAY, 1);
+ CreateTestCubemap();
+
+ if( m_TextureFormat != TEX_FORMAT_RGB9E5_SHAREDEXP &&
+ PixelFormatAttribs.ComponentType != COMPONENT_TYPE_COMPRESSED )
+ {
+ if( TexCaps.bTexture2DMSSupported && (BindFlags & (BIND_RENDER_TARGET|BIND_DEPTH_STENCIL)) != 0 )
+ {
+ if( PixelFormatAttribs.SupportsMS )
+ {
+ CreateTestTexture( RESOURCE_DIM_TEX_2D, 4 );
+ CreateTestTexture( RESOURCE_DIM_TEX_2D, 4 );
+ }
+ }
+ else
+ {
+ static bool FirstTime = true;
+ if( FirstTime )
+ {
+ LOG_WARNING_MESSAGE( "Texture 2D MS is not supported\n" );
+ FirstTime = false;
+ }
+ }
+
+ if( TexCaps.bTexture2DMSArraySupported && (BindFlags & (BIND_RENDER_TARGET|BIND_DEPTH_STENCIL)) != 0 )
+ {
+ if( PixelFormatAttribs.SupportsMS )
+ {
+ CreateTestTexture( RESOURCE_DIM_TEX_2D_ARRAY, 4 );
+ CreateTestTexture( RESOURCE_DIM_TEX_2D_ARRAY, 4 );
+ }
+ }
+ else
+ {
+ static bool FirstTime = true;
+ if( FirstTime )
+ {
+ LOG_WARNING_MESSAGE( "Texture 2D MS Array is not supported\n" );
+ FirstTime = false;
+ }
+ }
+ }
+
+ // Test texture 3D
+ if( PixelFormatAttribs.Tex3DFmt )
+ CreateTestTexture(RESOURCE_DIM_TEX_3D, 1);
+ }
+
+private:
+ void PrepareSubresourceData(TextureDesc &TexDesc,
+ TextureFormatInfo &PixelFormatAttribs,
+ std::vector< std::vector<Uint8> > &Data,
+ std::vector<TextureSubResData> &SubResources,
+ TextureData &InitData)
+ {
+
+ auto PixelSize = PixelFormatAttribs.ComponentSize * PixelFormatAttribs.NumComponents;
+ assert( PixelSize == m_PixelSize );
+
+ Uint32 ArrSize = (TexDesc.Type == RESOURCE_DIM_TEX_3D) ? 1 : TexDesc.ArraySize;
+ InitData.NumSubresources = ArrSize * TexDesc.MipLevels;
+ Data.resize(InitData.NumSubresources);
+ SubResources.resize(InitData.NumSubresources);
+ Uint32 SubRes = 0;
+ for(Uint32 Slice = 0; Slice < ArrSize; ++Slice)
+ {
+ for(Uint32 Mip = 0; Mip < TexDesc.MipLevels; ++Mip)
+ {
+ Uint32 MipWidth = std::max(TexDesc.Width >> Mip, 1U);
+ Uint32 MipHeight = std::max(TexDesc.Height >> Mip, 1U);
+ auto &CurrSubResData = Data[SubRes];
+ auto &SubResInfo = SubResources[SubRes];
+ SubResInfo.Stride = (MipWidth + 128) * PixelSize;
+ SubResInfo.Stride = (SubResInfo.Stride + 3) & (-4);
+ auto SubresDataSize = 0;
+ if(TexDesc.Type == RESOURCE_DIM_TEX_3D)
+ {
+ SubResInfo.DepthStride = SubResInfo.Stride * (MipHeight + 32);
+ Uint32 MipDeth = std::max(TexDesc.Depth >> Mip, 1U);
+ SubresDataSize = SubResInfo.DepthStride * MipDeth;
+ }
+ else
+ SubresDataSize = SubResInfo.Stride * MipHeight;
+
+ CurrSubResData.resize(SubresDataSize);
+ SubResInfo.pData = CurrSubResData.data();
+ ++SubRes;
+ }
+ }
+ InitData.pSubResources = SubResources.data();
+ }
+ void CreateTestTexture(RESOURCE_DIMENSION Type, Uint32 SampleCount)
+ {
+ TextureDesc TexDesc;
+ TexDesc.Name = "TestTextureCreation";
+ TexDesc.Type = Type;
+ TexDesc.Width = 211;
+ if( TexDesc.Type == RESOURCE_DIM_TEX_1D || TexDesc.Type == RESOURCE_DIM_TEX_1D_ARRAY )
+ TexDesc.Height = 1;
+ else
+ TexDesc.Height = 243;
+
+ if( TexDesc.Type == RESOURCE_DIM_TEX_3D )
+ TexDesc.Depth = 16;
+
+ if( TexDesc.Type == RESOURCE_DIM_TEX_1D_ARRAY || TexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY )
+ TexDesc.ArraySize = 16;
+
+ auto PixelFormatAttribs = m_pDevice->GetTextureFormatInfoExt(m_TextureFormat);
+ if( PixelFormatAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED )
+ {
+ TexDesc.Width = (TexDesc.Width+3) & (-4);
+ TexDesc.Height = (TexDesc.Height+3) & (-4);
+ }
+
+ TexDesc.MipLevels = SampleCount == 1 ? 0 : 1;
+ TexDesc.Format = m_TextureFormat;
+ TexDesc.Usage = USAGE_DEFAULT;
+ TexDesc.BindFlags = m_BindFlags;
+ if( SampleCount > 1 )
+ TexDesc.BindFlags &= ~BIND_UNORDERED_ACCESS;
+
+ TexDesc.SampleCount = SampleCount;
+
+ RefCntAutoPtr<Diligent::ITexture> pTestTex;
+ m_pDevice->CreateTexture( TexDesc, TextureData(), &pTestTex );
+ m_pTestCreateObjFromNativeRes->CreateTexture(pTestTex);
+ TexDesc.MipLevels = pTestTex->GetDesc().MipLevels;
+ if( SampleCount == 1 && m_bTestDataUpload )
+ {
+ std::vector< std::vector<Uint8> > Data;
+ std::vector<TextureSubResData> SubResources;
+ TextureData InitData;
+
+ PrepareSubresourceData(TexDesc, PixelFormatAttribs, Data, SubResources, InitData);
+
+ TexDesc.Name = "TestTexture2";
+ pTestTex.Release();
+ m_pDevice->CreateTexture( TexDesc, InitData, &pTestTex );
+ m_pTestCreateObjFromNativeRes->CreateTexture(pTestTex);
+ }
+
+ const auto &DeviceCaps = m_pDevice->GetDeviceCaps();
+ const auto &TextureCaps = DeviceCaps.TexCaps;
+ if( TextureCaps.bTextureViewSupported )
+ {
+ TextureViewDesc ViewDesc;
+ ViewDesc.TextureDim = TexDesc.Type;
+ if( TexDesc.Type == RESOURCE_DIM_TEX_1D_ARRAY || TexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY )
+ {
+ ViewDesc.FirstArraySlice = 3;
+ ViewDesc.NumArraySlices = (DeviceCaps.DevType == DeviceType::D3D11 || DeviceCaps.DevType == DeviceType::D3D12 || ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) ? 4 : 1;
+ }
+ else if(TexDesc.Type == RESOURCE_DIM_TEX_3D)
+ {
+ if( DeviceCaps.DevType == DeviceType::D3D11 || DeviceCaps.DevType == DeviceType::D3D12 )
+ {
+ ViewDesc.FirstDepthSlice = 3;
+ ViewDesc.NumDepthSlices = 4;
+ }
+ else
+ {
+ // OpenGL cannot create views for separate depth slices
+ ViewDesc.FirstDepthSlice = 0;
+ ViewDesc.NumDepthSlices = 1;
+ }
+ }
+ else
+ {
+ ViewDesc.FirstArraySlice = 0;
+ ViewDesc.NumArraySlices = 1;
+ }
+
+ if( SampleCount > 1 )
+ {
+ ViewDesc.MostDetailedMip = 0;
+ ViewDesc.NumMipLevels = 1;
+ }
+ else
+ {
+ ViewDesc.MostDetailedMip = 1;
+ ViewDesc.NumMipLevels = 2;
+ }
+
+ if( TexDesc.BindFlags & BIND_SHADER_RESOURCE )
+ {
+ ViewDesc.ViewType = TEXTURE_VIEW_SHADER_RESOURCE;
+ RefCntAutoPtr<ITextureView> pSRV;
+ pTestTex->CreateView( ViewDesc, &pSRV );
+ }
+
+ // RTV, DSV & UAV can reference only one mip level
+ ViewDesc.NumMipLevels = 1;
+
+ if( TexDesc.BindFlags & BIND_RENDER_TARGET )
+ {
+ ViewDesc.ViewType = TEXTURE_VIEW_RENDER_TARGET;
+ RefCntAutoPtr<ITextureView> pRTV;
+ pTestTex->CreateView( ViewDesc, &pRTV );
+ }
+
+ if( TexDesc.BindFlags & BIND_DEPTH_STENCIL )
+ {
+ ViewDesc.ViewType = TEXTURE_VIEW_DEPTH_STENCIL;
+ RefCntAutoPtr<ITextureView> pDSV;
+ pTestTex->CreateView( ViewDesc, &pDSV );
+ }
+
+ if( TexDesc.BindFlags & BIND_UNORDERED_ACCESS )
+ {
+ ViewDesc.ViewType = TEXTURE_VIEW_UNORDERED_ACCESS;
+ ViewDesc.AccessFlags = UAV_ACCESS_FLAG_READ | UAV_ACCESS_FLAG_WRITE;
+ RefCntAutoPtr<ITextureView> pUAV;
+ pTestTex->CreateView( ViewDesc, &pUAV );
+ }
+ }
+ else
+ {
+ static bool FirstTime = true;
+ if( FirstTime )
+ {
+ LOG_WARNING_MESSAGE("Texture views are not supported!\n");
+ FirstTime = false;
+ }
+ }
+
+ // It is necessary to call Flush() to force the driver to release the resources.
+ // Without flushing the command buffer, the memory is not released until sometimes
+ // later causing out-of-memory error
+ m_pDeviceContext->Flush();
+ }
+
+
+ void CreateTestCubemap()
+ {
+ TextureDesc TexDesc;
+ TexDesc.Name = "Test Cube MapTextureCreation";
+ TexDesc.Type = RESOURCE_DIM_TEX_CUBE;
+ TexDesc.Width = 256;
+ TexDesc.Height = 256;
+ TexDesc.ArraySize = 6;
+ TexDesc.MipLevels = 0;
+ TexDesc.Format = m_TextureFormat;
+ TexDesc.Usage = USAGE_DEFAULT;
+ TexDesc.BindFlags = m_BindFlags;
+ TexDesc.SampleCount = 1;
+
+ RefCntAutoPtr<Diligent::ITexture> pTestCubemap, pTestCubemapArr;
+ m_pDevice->CreateTexture( TexDesc, TextureData(), &pTestCubemap );
+ m_pTestCreateObjFromNativeRes->CreateTexture(pTestCubemap);
+ TexDesc.MipLevels = pTestCubemap->GetDesc().MipLevels;
+
+ auto PixelFormatAttribs = m_pDevice->GetTextureFormatInfoExt(m_TextureFormat);
+ if( m_bTestDataUpload )
+ {
+ std::vector< std::vector<Uint8> > Data;
+ std::vector<TextureSubResData> SubResources;
+ TextureData InitData;
+
+ PrepareSubresourceData(TexDesc, PixelFormatAttribs, Data, SubResources, InitData);
+
+ InitData.pSubResources = SubResources.data();
+ TexDesc.Name = "TestCubemap2";
+ pTestCubemap.Release();
+ m_pDevice->CreateTexture( TexDesc, InitData, &pTestCubemap );
+ m_pTestCreateObjFromNativeRes->CreateTexture(pTestCubemap);
+ }
+
+ const auto &DeviceCaps = m_pDevice->GetDeviceCaps();
+ const auto &TextureCaps = DeviceCaps.TexCaps;
+ if( TextureCaps.bTextureViewSupported )
+ {
+ TextureViewDesc ViewDesc;
+ if( TexDesc.BindFlags & BIND_SHADER_RESOURCE )
+ {
+ ViewDesc.TextureDim = RESOURCE_DIM_TEX_CUBE;
+ ViewDesc.ViewType = TEXTURE_VIEW_SHADER_RESOURCE;
+ ViewDesc.MostDetailedMip = 1;
+ ViewDesc.NumMipLevels = 6;
+ {
+ RefCntAutoPtr<ITextureView> pSRV;
+ pTestCubemap->CreateView( ViewDesc, &pSRV );
+ }
+
+ ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D;
+ ViewDesc.FirstArraySlice = 0;
+ ViewDesc.NumArraySlices = 1;
+ ViewDesc.MostDetailedMip = 2;
+ ViewDesc.NumMipLevels = 4;
+ {
+ RefCntAutoPtr<ITextureView> pSRV;
+ pTestCubemap->CreateView( ViewDesc, &pSRV );
+ }
+
+ ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY;
+ ViewDesc.FirstArraySlice = 2;
+ ViewDesc.NumArraySlices = 3;
+ {
+ RefCntAutoPtr<ITextureView> pSRV;
+ pTestCubemap->CreateView( ViewDesc, &pSRV );
+ }
+ }
+
+ // RTV, DSV & UAV can reference only one mip level
+ ViewDesc.NumMipLevels = 1;
+
+ if( TexDesc.BindFlags & BIND_RENDER_TARGET )
+ {
+ ViewDesc.ViewType = TEXTURE_VIEW_RENDER_TARGET;
+ ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D;
+ ViewDesc.FirstArraySlice = 0;
+ ViewDesc.NumArraySlices = 1;
+ {
+ RefCntAutoPtr<ITextureView> pRTV;
+ pTestCubemap->CreateView( ViewDesc, &pRTV );
+ }
+
+ ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY;
+ ViewDesc.FirstArraySlice = 2;
+ ViewDesc.NumArraySlices = 3;
+ {
+ RefCntAutoPtr<ITextureView> pRTV;
+ pTestCubemap->CreateView( ViewDesc, &pRTV );
+ }
+ }
+
+ if( TexDesc.BindFlags & BIND_DEPTH_STENCIL )
+ {
+ ViewDesc.ViewType = TEXTURE_VIEW_DEPTH_STENCIL;
+ ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D;
+ ViewDesc.NumArraySlices = 1;
+ ViewDesc.FirstArraySlice = 0;
+ ViewDesc.MostDetailedMip = 2;
+ {
+ RefCntAutoPtr<ITextureView> pDSV;
+ pTestCubemap->CreateView( ViewDesc, &pDSV );
+ }
+
+ ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY;
+ ViewDesc.NumArraySlices = 3;
+ ViewDesc.FirstArraySlice = 2;
+ {
+ RefCntAutoPtr<ITextureView> pDSV;
+ pTestCubemap->CreateView( ViewDesc, &pDSV );
+ }
+ }
+
+ if( TexDesc.BindFlags & BIND_UNORDERED_ACCESS )
+ {
+ ViewDesc.ViewType = TEXTURE_VIEW_UNORDERED_ACCESS;
+ ViewDesc.AccessFlags = UAV_ACCESS_FLAG_READ | UAV_ACCESS_FLAG_WRITE;
+ ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D;
+ ViewDesc.NumArraySlices = 1;
+ ViewDesc.FirstArraySlice = 0;
+ {
+ RefCntAutoPtr<ITextureView> pUAV;
+ pTestCubemap->CreateView( ViewDesc, &pUAV );
+ }
+
+ ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY;
+ if( DeviceCaps.DevType == DeviceType::OpenGL || DeviceCaps.DevType == DeviceType::OpenGLES )
+ {
+ ViewDesc.NumArraySlices = 1;
+ ViewDesc.FirstArraySlice = 2;
+ }
+ else
+ {
+ ViewDesc.NumArraySlices = 3;
+ ViewDesc.FirstArraySlice = 2;
+ }
+
+ {
+ RefCntAutoPtr<ITextureView> pUAV;
+ pTestCubemap->CreateView( ViewDesc, &pUAV );
+ }
+ }
+ }
+
+ if(DeviceCaps.TexCaps.bCubemapArraysSupported)
+ {
+ TexDesc.ArraySize = 24;
+ TexDesc.Type = RESOURCE_DIM_TEX_CUBE_ARRAY;
+
+ std::vector< std::vector<Uint8> > Data;
+ std::vector<TextureSubResData> SubResources;
+ TextureData InitData;
+
+ if( m_bTestDataUpload )
+ {
+ PrepareSubresourceData(TexDesc, PixelFormatAttribs, Data, SubResources, InitData);
+ }
+
+ TexDesc.Name = "TestCubemapArray";
+
+ m_pDevice->CreateTexture( TexDesc, InitData, &pTestCubemapArr );
+ m_pTestCreateObjFromNativeRes->CreateTexture(pTestCubemapArr);
+ }
+
+ // It is necessary to call Flush() to force the driver to release the resources.
+ // Without flushing the command buffer, the memory is not released until sometimes
+ // later causing out-of-memory error
+ m_pDeviceContext->Flush();
+ }
+ IRenderDevice *m_pDevice;
+ IDeviceContext *m_pDeviceContext;
+ Uint32 m_BindFlags;
+ TEXTURE_FORMAT m_TextureFormat;
+ Uint32 m_PixelSize;
+ Bool m_bTestDataUpload;
+ std::unique_ptr<TestCreateObjFromNativeRes> m_pTestCreateObjFromNativeRes;
+};
+
+TestTextureCreation::TestTextureCreation( IRenderDevice *pDevice, IDeviceContext *pContext ) :
+ m_pDevice(pDevice)
+{
+ TestTextureFormatAttribs();
+
+ TextureCreationVerifier Verifier(pDevice, pContext);
+ const Uint32 BindSRU = BIND_SHADER_RESOURCE | BIND_RENDER_TARGET | BIND_UNORDERED_ACCESS;
+ const Uint32 BindSR = BIND_SHADER_RESOURCE | BIND_RENDER_TARGET;
+ const Uint32 BindSD = BIND_SHADER_RESOURCE | BIND_DEPTH_STENCIL;
+ const Uint32 BindSU = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
+ const Uint32 BindD = BIND_DEPTH_STENCIL;
+ const Uint32 BindS = BIND_SHADER_RESOURCE;
+
+ struct TextureTestAttribs
+ {
+ TEXTURE_FORMAT Fmt;
+ Uint32 PixelSize;
+ Uint32 BindFlags;
+ Bool TestDataUpload;
+ const char* Name;
+ };
+
+ const TextureTestAttribs TestAttribs[] =
+ {
+ {TEX_FORMAT_RGBA32_FLOAT, 16, BindSRU, true, "RGBA32_FLOAT"},
+ {TEX_FORMAT_RGBA32_UINT, 16, BindSRU, true, "RGBA32_UINT"},
+ {TEX_FORMAT_RGBA32_SINT, 16, BindSRU, true, "RGBA32_SINT"},
+ //{TEX_FORMAT_RGB32_TYPELESS, , 5, "RGB32_TYPELESS"},
+
+ // These formats are ill-supported
+ //{TEX_FORMAT_RGB32_FLOAT, 12, BindS, true, "RGB32_FLOAT"},
+ //{TEX_FORMAT_RGB32_UINT, 12, BindS, true, "RGB32_UINT"},
+ //{TEX_FORMAT_RGB32_SINT, 12, BindS, true, "RGB32_SINT"},
+
+ //{TEX_FORMAT_RGBA16_TYPELESS, 8, BindSRU, true, "RGBA16_TYPELESS"},
+ {TEX_FORMAT_RGBA16_FLOAT, 8, BindSRU, true, "RGBA16_FLOAT"},
+ {TEX_FORMAT_RGBA16_UNORM, 8, BindSRU, true, "RGBA16_UNORM"},
+ {TEX_FORMAT_RGBA16_UINT, 8, BindSRU, true, "RGBA16_UINT"},
+ {TEX_FORMAT_RGBA16_SNORM, 8, BindSU, true, "RGBA16_SNORM"},
+ {TEX_FORMAT_RGBA16_SINT, 8, BindSRU, true, "RGBA16_SINT"},
+
+ //{TEX_FORMAT_RG32_TYPELESS, 8, BindSRU, true, "RG32_TYPELESS"},
+ {TEX_FORMAT_RG32_FLOAT, 8, BindSRU, true, "RG32_FLOAT"},
+ {TEX_FORMAT_RG32_UINT, 8, BindSRU, true, "RG32_UINT"},
+ {TEX_FORMAT_RG32_SINT, 8, BindSRU, true, "RG32_SINT"},
+
+ //{TEX_FORMAT_R32G8X24_TYPELESS, 8, BindD, false, "R32G8X24_TYPELESS"},
+ {TEX_FORMAT_D32_FLOAT_S8X24_UINT, 8, BindD, false, "D32_FLOAT_S8X24_UINT"},
+ //{TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS, 8, BindD, false, "R32_FLOAT_X8X24_TYPELESS"},
+ //{TEX_FORMAT_X32_TYPELESS_G8X24_UINT, 8, BindD, false, "X32_TYPELESS_G8X24_UINT"},
+
+ //{TEX_FORMAT_RGB10A2_TYPELESS, 4, BindSRU, true, "RGB10A2_TYPELESS"},
+ {TEX_FORMAT_RGB10A2_UNORM, 4, BindSRU, true, "RGB10A2_UNORM"},
+ {TEX_FORMAT_RGB10A2_UINT, 4, BindSRU, true, "RGB10A2_UINT"},
+ {TEX_FORMAT_R11G11B10_FLOAT, 4, BindSRU, false,"R11G11B10_FLOAT"},
+
+ //{TEX_FORMAT_RGBA8_TYPELESS, 4, BindSRU, true, "RGBA8_TYPELESS"},
+ {TEX_FORMAT_RGBA8_UNORM, 4, BindSRU, true, "RGBA8_UNORM"},
+ {TEX_FORMAT_RGBA8_UNORM_SRGB, 4, BindSR, true, "RGBA8_UNORM_SRGB"},
+ {TEX_FORMAT_RGBA8_UINT, 4, BindSRU, true, "RGBA8_UINT"},
+ {TEX_FORMAT_RGBA8_SNORM, 4, BindSU, true, "RGBA8_SNORM"},
+ {TEX_FORMAT_RGBA8_SINT, 4, BindSRU, true, "RGBA8_SINT"},
+
+ //{TEX_FORMAT_RG16_TYPELESS, 4, BindSRU, true, "RG16_TYPELESS"},
+ {TEX_FORMAT_RG16_FLOAT, 4, BindSRU, true, "RG16_FLOAT"},
+ {TEX_FORMAT_RG16_UNORM, 4, BindSRU, true, "RG16_UNORM"},
+ {TEX_FORMAT_RG16_UINT, 4, BindSRU, true, "RG16_UINT"},
+ {TEX_FORMAT_RG16_SNORM, 4, BindSU, true, "RG16_SNORM"},
+ {TEX_FORMAT_RG16_SINT, 4, BindSRU, true, "RG16_SINT"},
+
+ //{TEX_FORMAT_R32_TYPELESS, 4, BindSRU, true, "R32_TYPELESS"},
+ {TEX_FORMAT_D32_FLOAT, 4, BindD, true, "D32_FLOAT"},
+ {TEX_FORMAT_R32_FLOAT, 4, BindSRU, true, "R32_FLOAT"},
+ {TEX_FORMAT_R32_UINT, 4, BindSRU, true, "R32_UINT"},
+ {TEX_FORMAT_R32_SINT, 4, BindSRU, true, "R32_SINT"},
+
+ //{TEX_FORMAT_R24G8_TYPELESS, 4, BindD, true, "R24G8_TYPELESS"},
+ {TEX_FORMAT_D24_UNORM_S8_UINT, 4, BindD, true, "D24_UNORM_S8_UINT"},
+ //{TEX_FORMAT_R24_UNORM_X8_TYPELESS, 4, BindD, true, "R24_UNORM_X8_TYPELESS"},
+ //{TEX_FORMAT_X24_TYPELESS_G8_UINT, 4, BindD, true, "X24_TYPELESS_G8_UINT"},
+
+ //{TEX_FORMAT_RG8_TYPELESS, 2, BindSRU, true, "RG8_TYPELESS"},
+ {TEX_FORMAT_RG8_UNORM, 2, BindSRU, true, "RG8_UNORM"},
+ {TEX_FORMAT_RG8_UINT, 2, BindSRU, true, "RG8_UINT"},
+ {TEX_FORMAT_RG8_SNORM, 2, BindSU, true, "RG8_SNORM"},
+ {TEX_FORMAT_RG8_SINT, 2, BindSRU, true, "RG8_SINT"},
+
+ //{TEX_FORMAT_R16_TYPELESS, 2, BindSRU, true, "R16_TYPELESS"},
+ {TEX_FORMAT_R16_FLOAT, 2, BindSRU, true, "R16_FLOAT"},
+ {TEX_FORMAT_D16_UNORM, 2, BindD, true, "D16_UNORM"},
+ {TEX_FORMAT_R16_UNORM, 2, BindSRU, true, "R16_UNORM"},
+ {TEX_FORMAT_R16_UINT, 2, BindSRU, true, "R16_UINT"},
+ {TEX_FORMAT_R16_SNORM, 2, BindSU, true, "R16_SNORM"},
+ {TEX_FORMAT_R16_SINT, 2, BindSRU, true, "R16_SINT"},
+
+ //{TEX_FORMAT_R8_TYPELESS, 1, BindSRU, true, "R8_TYPELESS"},
+ {TEX_FORMAT_R8_UNORM, 1, BindSRU, true, "R8_UNORM"},
+ {TEX_FORMAT_R8_UINT, 1, BindSRU, true, "R8_UINT"},
+ {TEX_FORMAT_R8_SNORM, 1, BindSU, true, "R8_SNORM"},
+ {TEX_FORMAT_R8_SINT, 1, BindSRU, true, "R8_SINT"},
+ //{TEX_FORMAT_A8_UNORM, 1, BindSRU, true, "A8_UNORM"},
+ //{TEX_FORMAT_R1_UNORM, 1, BindSRU, true, "R1_UNORM"},
+
+ {TEX_FORMAT_RGB9E5_SHAREDEXP, 4, BindS, false, "RGB9E5_SHAREDEXP"},
+ //{TEX_FORMAT_RG8_B8G8_UNORM, 4, BindSRU, false, "RG8_B8G8_UNORM"},
+ //{TEX_FORMAT_G8R8_G8B8_UNORM, 4, BindSRU, false, "G8R8_G8B8_UNORM"},
+
+ //{TEX_FORMAT_BC1_TYPELESS, 16, BindS, false, "BC1_TYPELESS"},
+ {TEX_FORMAT_BC1_UNORM, 16, BindS, false, "BC1_UNORM"},
+ {TEX_FORMAT_BC1_UNORM_SRGB, 16, BindS, false, "BC1_UNORM_SRGB"},
+ //{TEX_FORMAT_BC2_TYPELESS, 16, BindS, false, "BC2_TYPELESS"},
+ {TEX_FORMAT_BC2_UNORM, 16, BindS, false, "BC2_UNORM"},
+ {TEX_FORMAT_BC2_UNORM_SRGB, 16, BindS, false, "BC2_UNORM_SRGB"},
+ //{TEX_FORMAT_BC3_TYPELESS, 16, BindS, false, "BC3_TYPELESS"},
+ {TEX_FORMAT_BC3_UNORM, 16, BindS, false, "BC3_UNORM"},
+ {TEX_FORMAT_BC3_UNORM_SRGB, 16, BindS, false, "BC3_UNORM_SRGB"},
+ //{TEX_FORMAT_BC4_TYPELESS, 16, BindS, false, "BC4_TYPELESS"},
+ {TEX_FORMAT_BC4_UNORM, 16, BindS, false, "BC4_UNORM"},
+ {TEX_FORMAT_BC4_SNORM, 16, BindS, false, "BC4_SNORM"},
+ //{TEX_FORMAT_BC5_TYPELESS, 16, BindS, false, "BC5_TYPELESS"},
+ {TEX_FORMAT_BC5_UNORM, 16, BindS, false, "BC5_UNORM"},
+ {TEX_FORMAT_BC5_SNORM, 16, BindS, false, "BC5_SNORM"},
+
+ //{TEX_FORMAT_B5G6R5_UNORM, 2, BindSRU, true, "B5G6R5_UNORM"},
+ //{TEX_FORMAT_B5G5R5A1_UNORM, 2, BindSRU, true, "B5G5R5A1_UNORM"},
+ //{TEX_FORMAT_BGRA8_UNORM, 4, BindSRU, true, "BGRA8_UNORM"},
+ //{TEX_FORMAT_BGRX8_UNORM, 4, BindSRU, true, "BGRX8_UNORM"},
+ //{TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, 4, BindS, false, "R10G10B10_XR_BIAS_A2_UNORM"},
+
+ //{TEX_FORMAT_BGRA8_TYPELESS, 4, BindSRU, true, "BGRA8_TYPELESS"},
+ //{TEX_FORMAT_BGRA8_UNORM_SRGB, 4, BindSR, true, "BGRA8_UNORM_SRGB",},
+ //{TEX_FORMAT_BGRX8_TYPELESS, 4, BindSRU, true, "BGRX8_TYPELESS"},
+ //{TEX_FORMAT_BGRX8_UNORM_SRGB, 4, BindSR, true, "BGRX8_UNORM_SRGB",},
+
+ //{TEX_FORMAT_BC6H_TYPELESS, 16, BindS, false, "BC6H_TYPELESS"},
+ {TEX_FORMAT_BC6H_UF16, 16, BindS, false, "BC6H_UF16"},
+ {TEX_FORMAT_BC6H_SF16, 16, BindS, false, "BC6H_SF16"},
+ //{TEX_FORMAT_BC7_TYPELESS, 16, BindS, false, "BC7_TYPELESS"},
+ {TEX_FORMAT_BC7_UNORM, 16, BindS, false, "BC7_UNORM"},
+ {TEX_FORMAT_BC7_UNORM_SRGB, 16, BindS, false, "BC7_UNORM_SRGB"},
+ };
+ for(int Test = 0; Test < _countof(TestAttribs); ++Test)
+ {
+ const auto &CurrAttrs = TestAttribs[Test];
+ const auto PixelFormatAttribs = pDevice->GetTextureFormatInfoExt(CurrAttrs.Fmt);
+ if( !PixelFormatAttribs.Supported )
+ {
+ LOG_WARNING_MESSAGE( "Texture format ", CurrAttrs.Name, " is not supported!\n" );
+ continue;
+ }
+ assert(CurrAttrs.PixelSize == PixelFormatAttribs.ComponentSize * PixelFormatAttribs.NumComponents ||
+ PixelFormatAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED);
+ Verifier.Test(CurrAttrs.Fmt, CurrAttrs.PixelSize, CurrAttrs.BindFlags, CurrAttrs.TestDataUpload);
+ }
+}
+
+void TestTextureCreation::CheckFormatSize(TEXTURE_FORMAT *begin, TEXTURE_FORMAT *end, Uint32 RefSize)
+{
+ for(auto fmt = begin; fmt != end; ++fmt)
+ {
+ auto FmtAttrs = m_pDevice->GetTextureFormatInfo(*fmt);
+ assert(FmtAttrs.ComponentSize * FmtAttrs.NumComponents == RefSize);
+ }
+}
+
+void TestTextureCreation::CheckNumComponents(TEXTURE_FORMAT *begin, TEXTURE_FORMAT *end, Uint32 RefComponents)
+{
+ for(auto fmt = begin; fmt != end; ++fmt)
+ {
+ auto FmtAttrs = m_pDevice->GetTextureFormatInfo(*fmt);
+ assert(FmtAttrs.NumComponents == RefComponents);
+ }
+}
+
+void TestTextureCreation::CheckComponentType(TEXTURE_FORMAT *begin, TEXTURE_FORMAT *end, COMPONENT_TYPE RefType)
+{
+ for(auto fmt = begin; fmt != end; ++fmt)
+ {
+ auto FmtAttrs = m_pDevice->GetTextureFormatInfo(*fmt);
+ assert(FmtAttrs.ComponentType == RefType);
+ }
+}
+
+void TestTextureCreation::TestTextureFormatAttribs()
+{
+ TEXTURE_FORMAT _16ByteFormats[] =
+ {
+ TEX_FORMAT_RGBA32_TYPELESS, TEX_FORMAT_RGBA32_FLOAT, TEX_FORMAT_RGBA32_UINT, TEX_FORMAT_RGBA32_SINT
+ };
+ CheckFormatSize(std::begin(_16ByteFormats), std::end(_16ByteFormats), 16);
+
+ TEXTURE_FORMAT _12ByteFormats[] =
+ {
+ TEX_FORMAT_RGB32_TYPELESS, TEX_FORMAT_RGB32_FLOAT, TEX_FORMAT_RGB32_UINT, TEX_FORMAT_RGB32_SINT
+ };
+ CheckFormatSize(std::begin(_12ByteFormats), std::end(_12ByteFormats), 12);
+
+ TEXTURE_FORMAT _8ByteFormats[] =
+ {
+ TEX_FORMAT_RGBA16_TYPELESS, TEX_FORMAT_RGBA16_FLOAT, TEX_FORMAT_RGBA16_UNORM, TEX_FORMAT_RGBA16_UINT, TEX_FORMAT_RGBA16_SNORM, TEX_FORMAT_RGBA16_SINT,
+ TEX_FORMAT_RG32_TYPELESS, TEX_FORMAT_RG32_FLOAT, TEX_FORMAT_RG32_UINT, TEX_FORMAT_RG32_SINT,
+ TEX_FORMAT_R32G8X24_TYPELESS, TEX_FORMAT_D32_FLOAT_S8X24_UINT, TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS, TEX_FORMAT_X32_TYPELESS_G8X24_UINT
+ };
+ CheckFormatSize(std::begin(_8ByteFormats), std::end(_8ByteFormats), 8);
+
+ TEXTURE_FORMAT _4ByteFormats[] =
+ {
+ TEX_FORMAT_RGB10A2_TYPELESS, TEX_FORMAT_RGB10A2_UNORM, TEX_FORMAT_RGB10A2_UINT, TEX_FORMAT_R11G11B10_FLOAT,
+ TEX_FORMAT_RGBA8_TYPELESS, TEX_FORMAT_RGBA8_UNORM, TEX_FORMAT_RGBA8_UNORM_SRGB, TEX_FORMAT_RGBA8_UINT, TEX_FORMAT_RGBA8_SNORM, TEX_FORMAT_RGBA8_SINT,
+ TEX_FORMAT_RG16_TYPELESS, TEX_FORMAT_RG16_FLOAT, TEX_FORMAT_RG16_UNORM, TEX_FORMAT_RG16_UINT, TEX_FORMAT_RG16_SNORM, TEX_FORMAT_RG16_SINT,
+ TEX_FORMAT_R32_TYPELESS, TEX_FORMAT_D32_FLOAT, TEX_FORMAT_R32_FLOAT, TEX_FORMAT_R32_UINT, TEX_FORMAT_R32_SINT,
+ TEX_FORMAT_R24G8_TYPELESS, TEX_FORMAT_D24_UNORM_S8_UINT, TEX_FORMAT_R24_UNORM_X8_TYPELESS, TEX_FORMAT_X24_TYPELESS_G8_UINT,
+ TEX_FORMAT_RGB9E5_SHAREDEXP, TEX_FORMAT_RG8_B8G8_UNORM, TEX_FORMAT_G8R8_G8B8_UNORM,
+ TEX_FORMAT_BGRA8_UNORM, TEX_FORMAT_BGRX8_UNORM, TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM,
+ TEX_FORMAT_BGRA8_TYPELESS, TEX_FORMAT_BGRA8_UNORM_SRGB, TEX_FORMAT_BGRX8_TYPELESS, TEX_FORMAT_BGRX8_UNORM_SRGB
+ };
+ CheckFormatSize(std::begin(_4ByteFormats), std::end(_4ByteFormats), 4);
+
+ TEXTURE_FORMAT _2ByteFormats[] =
+ {
+ TEX_FORMAT_RG8_TYPELESS, TEX_FORMAT_RG8_UNORM, TEX_FORMAT_RG8_UINT, TEX_FORMAT_RG8_SNORM, TEX_FORMAT_RG8_SINT,
+ TEX_FORMAT_R16_TYPELESS, TEX_FORMAT_R16_FLOAT, TEX_FORMAT_D16_UNORM, TEX_FORMAT_R16_UNORM, TEX_FORMAT_R16_UINT, TEX_FORMAT_R16_SNORM, TEX_FORMAT_R16_SINT,
+ TEX_FORMAT_B5G6R5_UNORM, TEX_FORMAT_B5G5R5A1_UNORM
+ };
+ CheckFormatSize(std::begin(_2ByteFormats), std::end(_2ByteFormats), 2);
+
+ TEXTURE_FORMAT _1ByteFormats[] =
+ {
+ TEX_FORMAT_R8_TYPELESS, TEX_FORMAT_R8_UNORM, TEX_FORMAT_R8_UINT, TEX_FORMAT_R8_SNORM, TEX_FORMAT_R8_SINT, TEX_FORMAT_A8_UNORM, //TEX_FORMAT_R1_UNORM
+ };
+ CheckFormatSize(std::begin(_1ByteFormats), std::end(_1ByteFormats), 1);
+
+ TEXTURE_FORMAT _4ComponentFormats[] =
+ {
+ TEX_FORMAT_RGBA32_TYPELESS, TEX_FORMAT_RGBA32_FLOAT, TEX_FORMAT_RGBA32_UINT, TEX_FORMAT_RGBA32_SINT,
+ TEX_FORMAT_RGBA16_TYPELESS, TEX_FORMAT_RGBA16_FLOAT, TEX_FORMAT_RGBA16_UNORM, TEX_FORMAT_RGBA16_UINT, TEX_FORMAT_RGBA16_SNORM, TEX_FORMAT_RGBA16_SINT,
+ TEX_FORMAT_RGBA8_TYPELESS, TEX_FORMAT_RGBA8_UNORM, TEX_FORMAT_RGBA8_UNORM_SRGB, TEX_FORMAT_RGBA8_UINT, TEX_FORMAT_RGBA8_SNORM, TEX_FORMAT_RGBA8_SINT,
+ TEX_FORMAT_RG8_B8G8_UNORM, TEX_FORMAT_G8R8_G8B8_UNORM,
+ TEX_FORMAT_BGRA8_UNORM, TEX_FORMAT_BGRX8_UNORM, TEX_FORMAT_BGRA8_TYPELESS, TEX_FORMAT_BGRA8_UNORM_SRGB, TEX_FORMAT_BGRX8_TYPELESS, TEX_FORMAT_BGRX8_UNORM_SRGB
+ };
+ CheckNumComponents(std::begin(_4ComponentFormats), std::end(_4ComponentFormats), 4);
+
+ TEXTURE_FORMAT _3ComponentFormats[] =
+ {
+ TEX_FORMAT_RGB32_TYPELESS, TEX_FORMAT_RGB32_FLOAT, TEX_FORMAT_RGB32_UINT, TEX_FORMAT_RGB32_SINT,
+
+ };
+ CheckNumComponents(std::begin(_3ComponentFormats), std::end(_3ComponentFormats), 3);
+
+ TEXTURE_FORMAT _2ComponentFormats[] =
+ {
+ TEX_FORMAT_RG32_TYPELESS, TEX_FORMAT_RG32_FLOAT, TEX_FORMAT_RG32_UINT, TEX_FORMAT_RG32_SINT,
+ TEX_FORMAT_R32G8X24_TYPELESS, TEX_FORMAT_D32_FLOAT_S8X24_UINT, TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS, TEX_FORMAT_X32_TYPELESS_G8X24_UINT,
+ TEX_FORMAT_RG16_TYPELESS, TEX_FORMAT_RG16_FLOAT, TEX_FORMAT_RG16_UNORM, TEX_FORMAT_RG16_UINT, TEX_FORMAT_RG16_SNORM, TEX_FORMAT_RG16_SINT,
+ TEX_FORMAT_RG8_TYPELESS, TEX_FORMAT_RG8_UNORM, TEX_FORMAT_RG8_UINT, TEX_FORMAT_RG8_SNORM, TEX_FORMAT_RG8_SINT
+ };
+ CheckNumComponents(std::begin(_2ComponentFormats), std::end(_2ComponentFormats), 2);
+
+ TEXTURE_FORMAT _1ComponentFormats[] =
+ {
+ TEX_FORMAT_RGB10A2_TYPELESS, TEX_FORMAT_RGB10A2_UNORM, TEX_FORMAT_RGB10A2_UINT, TEX_FORMAT_R11G11B10_FLOAT,
+ TEX_FORMAT_R32_TYPELESS, TEX_FORMAT_D32_FLOAT, TEX_FORMAT_R32_FLOAT, TEX_FORMAT_R32_UINT, TEX_FORMAT_R32_SINT,
+ TEX_FORMAT_R24G8_TYPELESS, TEX_FORMAT_D24_UNORM_S8_UINT, TEX_FORMAT_R24_UNORM_X8_TYPELESS, TEX_FORMAT_X24_TYPELESS_G8_UINT,
+ TEX_FORMAT_R16_TYPELESS, TEX_FORMAT_R16_FLOAT, TEX_FORMAT_D16_UNORM, TEX_FORMAT_R16_UNORM, TEX_FORMAT_R16_UINT, TEX_FORMAT_R16_SNORM, TEX_FORMAT_R16_SINT,
+ TEX_FORMAT_R8_TYPELESS, TEX_FORMAT_R8_UNORM, TEX_FORMAT_R8_UINT, TEX_FORMAT_R8_SNORM, TEX_FORMAT_R8_SINT, TEX_FORMAT_A8_UNORM, //TEX_FORMAT_R1_UNORM
+ TEX_FORMAT_RGB9E5_SHAREDEXP,
+ TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, TEX_FORMAT_B5G6R5_UNORM, TEX_FORMAT_B5G5R5A1_UNORM
+ };
+ CheckNumComponents(std::begin(_1ComponentFormats), std::end(_1ComponentFormats), 1);
+
+
+ TEXTURE_FORMAT FloatFormats[] =
+ {
+ TEX_FORMAT_RGBA32_FLOAT,
+ TEX_FORMAT_RGB32_FLOAT,
+ TEX_FORMAT_RGBA16_FLOAT,
+ TEX_FORMAT_RG32_FLOAT,
+ TEX_FORMAT_RG16_FLOAT,
+ TEX_FORMAT_R32_FLOAT,
+ TEX_FORMAT_R16_FLOAT
+ };
+ CheckComponentType(std::begin(FloatFormats), std::end(FloatFormats), COMPONENT_TYPE_FLOAT);
+
+ TEXTURE_FORMAT SintFormats[] =
+ {
+ TEX_FORMAT_RGBA32_SINT,
+ TEX_FORMAT_RGB32_SINT,
+ TEX_FORMAT_RGBA16_SINT,
+ TEX_FORMAT_RG32_SINT,
+ TEX_FORMAT_RGBA8_SINT,
+ TEX_FORMAT_RG16_SINT,
+ TEX_FORMAT_R32_SINT,
+ TEX_FORMAT_RG8_SINT,
+ TEX_FORMAT_R16_SINT,
+ TEX_FORMAT_R8_SINT
+ };
+ CheckComponentType(std::begin(SintFormats), std::end(SintFormats), COMPONENT_TYPE_SINT);
+
+ TEXTURE_FORMAT UintFormats[] =
+ {
+ TEX_FORMAT_RGBA32_UINT,
+ TEX_FORMAT_RGB32_UINT,
+ TEX_FORMAT_RGBA16_UINT,
+ TEX_FORMAT_RG32_UINT,
+ TEX_FORMAT_RGBA8_UINT,
+ TEX_FORMAT_RG16_UINT,
+ TEX_FORMAT_R32_UINT,
+ TEX_FORMAT_RG8_UINT,
+ TEX_FORMAT_R16_UINT,
+ TEX_FORMAT_R8_UINT
+ };
+ CheckComponentType(std::begin(UintFormats), std::end(UintFormats), COMPONENT_TYPE_UINT);
+
+ TEXTURE_FORMAT UnormFormats[] =
+ {
+ TEX_FORMAT_RGBA16_UNORM,
+ TEX_FORMAT_RGBA8_UNORM,
+ TEX_FORMAT_RG16_UNORM,
+ TEX_FORMAT_RG8_UNORM,
+ TEX_FORMAT_R16_UNORM,
+ TEX_FORMAT_R8_UNORM,
+ TEX_FORMAT_A8_UNORM,
+ TEX_FORMAT_R1_UNORM,
+ TEX_FORMAT_RG8_B8G8_UNORM,
+ TEX_FORMAT_G8R8_G8B8_UNORM,
+ TEX_FORMAT_BGRA8_UNORM,
+ TEX_FORMAT_BGRX8_UNORM
+ };
+ CheckComponentType(std::begin(UnormFormats), std::end(UnormFormats), COMPONENT_TYPE_UNORM);
+
+ TEXTURE_FORMAT UnormSRGBFormats[] =
+ {
+ TEX_FORMAT_RGBA8_UNORM_SRGB,
+ TEX_FORMAT_BGRA8_UNORM_SRGB,
+ TEX_FORMAT_BGRX8_UNORM_SRGB
+ };
+ CheckComponentType(std::begin(UnormSRGBFormats), std::end(UnormSRGBFormats), COMPONENT_TYPE_UNORM_SRGB);
+
+ TEXTURE_FORMAT SnormFormats[] =
+ {
+ TEX_FORMAT_RGBA16_SNORM,
+ TEX_FORMAT_RGBA8_SNORM,
+ TEX_FORMAT_RG16_SNORM,
+ TEX_FORMAT_RG8_SNORM,
+ TEX_FORMAT_R16_SNORM,
+ TEX_FORMAT_R8_SNORM
+ };
+ CheckComponentType(std::begin(SnormFormats), std::end(SnormFormats), COMPONENT_TYPE_SNORM);
+
+ TEXTURE_FORMAT UndefinedFormats[] =
+ {
+ TEX_FORMAT_RGBA32_TYPELESS,
+ TEX_FORMAT_RGB32_TYPELESS,
+ TEX_FORMAT_RGBA16_TYPELESS,
+ TEX_FORMAT_RG32_TYPELESS,
+ TEX_FORMAT_RGBA8_TYPELESS,
+ TEX_FORMAT_RG16_TYPELESS,
+ TEX_FORMAT_R32_TYPELESS,
+ TEX_FORMAT_RG8_TYPELESS,
+ TEX_FORMAT_R16_TYPELESS,
+ TEX_FORMAT_R8_TYPELESS,
+ TEX_FORMAT_BGRA8_TYPELESS,
+ TEX_FORMAT_BGRX8_TYPELESS
+ };
+ CheckComponentType(std::begin(UndefinedFormats), std::end(UndefinedFormats), COMPONENT_TYPE_UNDEFINED);
+
+ TEXTURE_FORMAT DepthFormats[] =
+ {
+ TEX_FORMAT_D32_FLOAT,
+ TEX_FORMAT_D16_UNORM
+ };
+ CheckComponentType(std::begin(DepthFormats), std::end(DepthFormats), COMPONENT_TYPE_DEPTH);
+
+ TEXTURE_FORMAT DepthStencilFormats[] =
+ {
+ TEX_FORMAT_R32G8X24_TYPELESS,
+ TEX_FORMAT_D32_FLOAT_S8X24_UINT,
+ TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS,
+ TEX_FORMAT_X32_TYPELESS_G8X24_UINT,
+ TEX_FORMAT_R24G8_TYPELESS,
+ TEX_FORMAT_D24_UNORM_S8_UINT,
+ TEX_FORMAT_R24_UNORM_X8_TYPELESS,
+ TEX_FORMAT_X24_TYPELESS_G8_UINT
+ };
+ CheckComponentType(std::begin(DepthStencilFormats), std::end(DepthStencilFormats), COMPONENT_TYPE_DEPTH_STENCIL);
+
+ TEXTURE_FORMAT CompoundFormats[] =
+ {
+ TEX_FORMAT_RGB10A2_TYPELESS,
+ TEX_FORMAT_RGB10A2_UNORM,
+ TEX_FORMAT_RGB10A2_UINT,
+ TEX_FORMAT_RGB9E5_SHAREDEXP,
+ TEX_FORMAT_R11G11B10_FLOAT,
+ TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM,
+ TEX_FORMAT_B5G6R5_UNORM,
+ TEX_FORMAT_B5G5R5A1_UNORM
+ };
+ CheckComponentType(std::begin(CompoundFormats), std::end(CompoundFormats), COMPONENT_TYPE_COMPOUND);
+
+
+ TEXTURE_FORMAT CompressedFormats[] =
+ {
+ TEX_FORMAT_BC1_TYPELESS, TEX_FORMAT_BC1_UNORM, TEX_FORMAT_BC1_UNORM_SRGB,
+ TEX_FORMAT_BC2_TYPELESS, TEX_FORMAT_BC2_UNORM, TEX_FORMAT_BC2_UNORM_SRGB,
+ TEX_FORMAT_BC3_TYPELESS, TEX_FORMAT_BC3_UNORM, TEX_FORMAT_BC3_UNORM_SRGB,
+ TEX_FORMAT_BC4_TYPELESS, TEX_FORMAT_BC4_UNORM, TEX_FORMAT_BC4_SNORM,
+ TEX_FORMAT_BC5_TYPELESS, TEX_FORMAT_BC5_UNORM, TEX_FORMAT_BC5_SNORM,
+ TEX_FORMAT_BC6H_TYPELESS, TEX_FORMAT_BC6H_UF16, TEX_FORMAT_BC6H_SF16,
+ TEX_FORMAT_BC7_TYPELESS, TEX_FORMAT_BC7_UNORM, TEX_FORMAT_BC7_UNORM_SRGB
+ };
+ CheckComponentType(std::begin(CompressedFormats), std::end(CompressedFormats), COMPONENT_TYPE_COMPRESSED);
+}
diff --git a/Tests/TestApp/src/TestTexturing.cpp b/Tests/TestApp/src/TestTexturing.cpp
new file mode 100644
index 0000000..69f0a49
--- /dev/null
+++ b/Tests/TestApp/src/TestTexturing.cpp
@@ -0,0 +1,285 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include <math.h>
+#include "TestTexturing.h"
+#include "GraphicsUtilities.h"
+#include "BasicShaderSourceStreamFactory.h"
+
+using namespace Diligent;
+
+TestTexturing::TestTexturing() :
+ m_iTestTexWidth(512),
+ m_iTestTexHeight(512),
+ m_iMipLevels(8),
+ m_TextureFormat(TEX_FORMAT_UNKNOWN)
+{
+}
+
+void TestTexturing::GenerateTextureData(IRenderDevice *pRenderDevice, std::vector<Uint8> &Data, std::vector<TextureSubResData> &SubResouces, const TextureDesc &TexDesc, const float *ColorOffset)
+{
+ Data.clear();
+ Uint32 CurrLevelOffset = 0;
+ std::vector<Uint32> LevelDataOffsets(TexDesc.MipLevels);
+ SubResouces.resize(TexDesc.MipLevels);
+
+ auto PixelFormatAttribs = pRenderDevice->GetTextureFormatInfoExt(TexDesc.Format);
+ auto PixelSize = PixelFormatAttribs.ComponentSize * PixelFormatAttribs.NumComponents;
+
+ for(Uint32 Level = 0; Level < TexDesc.MipLevels; ++Level)
+ {
+ Uint32 MipWidth = TexDesc.Width >> Level;
+ Uint32 MipHeight = TexDesc.Height >> Level;
+ auto Stride = (MipWidth + 64) * PixelSize;
+
+ Data.resize(Data.size() + Stride * MipHeight);
+ auto *pCurrLevelPtr = &Data[CurrLevelOffset];
+ LevelDataOffsets[Level] = CurrLevelOffset;
+ SubResouces[Level].Stride = Stride;
+ for(Uint32 j=0; j<MipHeight; ++j)
+ for(Uint32 i=0; i<MipWidth; ++i)
+ {
+ float Color[4] =
+ {
+ (float)i/(float)MipWidth * 1.5f + (ColorOffset ? ColorOffset[0] : 0.f),
+ (float)j/(float)MipHeight * 1.7f+ (ColorOffset ? ColorOffset[1] : 0.f),
+ (float)j/(float)MipHeight / 1.3f + (float)i/(float)MipWidth/1.1f + (ColorOffset ? ColorOffset[2] : 0.f),
+ 1.f + (ColorOffset ? ColorOffset[3] : 0.f)
+ };
+ for(Uint32 iCmp = 0; iCmp < PixelFormatAttribs.NumComponents; ++iCmp)
+ {
+ float fCurrCmpCol = Color[iCmp];
+ fCurrCmpCol = fCurrCmpCol - floor(fCurrCmpCol);
+ void *pDstCmp = pCurrLevelPtr + (i*PixelSize + iCmp * PixelFormatAttribs.ComponentSize + j*Stride);
+ switch(PixelFormatAttribs.ComponentType)
+ {
+ case COMPONENT_TYPE_FLOAT:
+ *((float*)pDstCmp) = fCurrCmpCol;
+ break;
+
+ case COMPONENT_TYPE_SNORM:
+ if( PixelFormatAttribs.ComponentSize == 1 )
+ *((Int8*)pDstCmp) = (Int8) std::min( std::max(fCurrCmpCol*127.f, -127.f), 127.f );
+ else if( PixelFormatAttribs.ComponentSize == 2 )
+ *((Int16*)pDstCmp) = (Int16) std::min( std::max(fCurrCmpCol*32767.f, -32767.f), 32767.f );
+ else
+ assert(false);
+ break;
+
+ case COMPONENT_TYPE_UNORM_SRGB:
+ case COMPONENT_TYPE_UNORM:
+ if( PixelFormatAttribs.ComponentSize == 1 )
+ *((Uint8*)pDstCmp) = (Uint8) std::min( std::max(fCurrCmpCol*255,0.f), 255.f );
+ else if( PixelFormatAttribs.ComponentSize == 2 )
+ *((Uint16*)pDstCmp) = (Uint16) std::min( std::max(fCurrCmpCol*65535.f,0.f), 65535.f );
+ else
+ assert(false);
+ break;
+
+ case COMPONENT_TYPE_SINT:
+ if( PixelFormatAttribs.ComponentSize == 1 )
+ *((Int8*)pDstCmp) = (Int8) std::min( std::max(fCurrCmpCol*127.f, -127.f), 127.f );
+ else if( PixelFormatAttribs.ComponentSize == 2 )
+ *((Int16*)pDstCmp) = (Int16) std::min( std::max(fCurrCmpCol*127.f, -127.f), 127.f );
+ else
+ assert(false);
+ break;
+
+ case COMPONENT_TYPE_UINT:
+ if( PixelFormatAttribs.ComponentSize == 1 )
+ *((Uint8*)pDstCmp) = (Uint8) std::min( std::max(fCurrCmpCol*255,0.f), 255.f );
+ else if( PixelFormatAttribs.ComponentSize == 2 )
+ *((Uint16*)pDstCmp) = (Uint16) std::min( std::max(fCurrCmpCol*255,0.f), 255.f );
+ else
+ assert(false);
+ break;
+
+ default: assert("Unsupport component type" && false);
+ }
+ }
+ }
+ CurrLevelOffset += Stride * MipHeight;
+ }
+ for(Uint32 Level = 0; Level < TexDesc.MipLevels; ++Level)
+ {
+ SubResouces[Level].pData = Data.data() + LevelDataOffsets[Level];
+ }
+}
+
+
+void TestTexturing::Init( IRenderDevice *pDevice, IDeviceContext *pDeviceContext, TEXTURE_FORMAT TexFormat, bool bUseOpenGL, float fMinXCoord, float fMinYCoord, float fXExtent, float fYExtent )
+{
+ m_pRenderDevice = pDevice;
+ m_TextureFormat = TexFormat;
+ m_pDeviceContext = pDeviceContext;
+
+ float Vertices[] =
+ {
+ 0, 0, 0, 0,1,
+ 0, 1, 0, 0,0,
+ 1, 0, 0, 1,1,
+ 1, 1, 0, 1,0
+ };
+ for(int v=0; v < 4; ++v)
+ {
+ Vertices[v*5+0] = Vertices[v*5+0] * fXExtent + fMinXCoord;
+ Vertices[v*5+1] = Vertices[v*5+1] * fYExtent + fMinYCoord;
+ }
+
+ {
+ Diligent::BufferDesc BuffDesc;
+ BuffDesc.uiSizeInBytes = sizeof(Vertices);
+ BuffDesc.BindFlags = BIND_VERTEX_BUFFER;
+ BuffDesc.Usage = USAGE_STATIC;
+ Diligent::BufferData BuffData;
+ BuffData.pData = Vertices;
+ BuffData.DataSize = BuffDesc.uiSizeInBytes;
+ m_pRenderDevice->CreateBuffer(BuffDesc, BuffData, &m_pVertexBuff);
+ }
+
+ auto PixelFormatAttribs = m_pRenderDevice->GetTextureFormatInfoExt(m_TextureFormat);
+
+ ShaderCreationAttribs CreationAttrs;
+ BasicShaderSourceStreamFactory BasicSSSFactory;
+ CreationAttrs.pShaderSourceStreamFactory = &BasicSSSFactory;
+ CreationAttrs.Desc.TargetProfile = bUseOpenGL ? SHADER_PROFILE_GL_4_2 : SHADER_PROFILE_DX_5_0;
+
+ RefCntAutoPtr<Diligent::IShader> pVS, pPS;
+ {
+ CreationAttrs.FilePath = bUseOpenGL ? "Shaders\\TextureTestGL.vsh" : "Shaders\\TextureTestDX.vsh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ m_pRenderDevice->CreateShader( CreationAttrs, &pVS );
+ }
+
+ bool bIsIntTexture = PixelFormatAttribs.ComponentType == COMPONENT_TYPE_UINT ||
+ PixelFormatAttribs.ComponentType == COMPONENT_TYPE_SINT;
+ {
+ if( bIsIntTexture )
+ CreationAttrs.FilePath = bUseOpenGL ? "Shaders\\TextureIntTestGL.psh" : "Shaders\\TextureIntTestDX.psh";
+ else
+ CreationAttrs.FilePath = bUseOpenGL ? "Shaders\\TextureTestGL.psh" : "Shaders\\TextureTestDX.psh";
+ CreationAttrs.Desc.ShaderType = SHADER_TYPE_PIXEL;
+
+ StaticSamplerDesc StaticSampler;
+ // On Intel HW, only point filtering sampler correctly works with an integer texture.
+ // If the sampler defines linear filtering, the texture is not properly bound to the
+ // sampler unit and zero is always returned.
+ // Note that on NVidia HW this works fine.
+ auto FilterType = bIsIntTexture ? FILTER_TYPE_POINT : FILTER_TYPE_LINEAR;
+ StaticSampler.Desc.MinFilter = FilterType;
+ StaticSampler.Desc.MagFilter = FilterType;
+ StaticSampler.Desc.MipFilter = FilterType;
+ StaticSampler.TextureName = "g_tex2DTest";
+ CreationAttrs.Desc.NumStaticSamplers = 1;
+ CreationAttrs.Desc.StaticSamplers = &StaticSampler;
+ m_pRenderDevice->CreateShader( CreationAttrs, &pPS );
+ }
+
+ {
+ SamplerDesc SamplerDesc;
+ // On Intel HW, only point filtering sampler correctly works with an integer texture.
+ // If the sampler defines linear filtering, the texture is not properly bound to the
+ // sampler unit and zero is always returned.
+ // Note that on NVidia HW this works fine.
+ auto FilterType = bIsIntTexture ? FILTER_TYPE_POINT : FILTER_TYPE_LINEAR;
+ SamplerDesc.MinFilter = FilterType;
+ SamplerDesc.MagFilter = FilterType;
+ SamplerDesc.MipFilter = FilterType;
+ m_pRenderDevice->CreateSampler( SamplerDesc, &m_pSampler );
+ }
+
+ {
+ TextureDesc TexDesc;
+ TexDesc.Type = RESOURCE_DIM_TEX_2D;
+ TexDesc.Width = m_iTestTexWidth;
+ TexDesc.Height = m_iTestTexHeight;
+ TexDesc.MipLevels = m_iMipLevels;
+ TexDesc.Usage = USAGE_STATIC;
+ TexDesc.Format = m_TextureFormat;
+ TexDesc.BindFlags = BIND_SHADER_RESOURCE;
+ TexDesc.Name = "Test Texture";
+
+ std::vector<Uint8> Data;
+ std::vector<TextureSubResData> SubResouces;
+ GenerateTextureData(m_pRenderDevice, Data, SubResouces, TexDesc);
+ TextureData TexData;
+ TexData.pSubResources = SubResouces.data();
+ TexData.NumSubresources = (Uint32)SubResouces.size();
+
+ m_pRenderDevice->CreateTexture( TexDesc, TexData, &m_pTexture );
+ }
+
+ {
+ RefCntAutoPtr<ITextureView> pDefaultSRV;
+ TextureViewDesc ViewDesc;
+ ViewDesc.ViewType = TEXTURE_VIEW_SHADER_RESOURCE;
+ m_pTexture->CreateView( ViewDesc, &pDefaultSRV );
+ pDefaultSRV->SetSampler( m_pSampler );
+ ResourceMappingEntry Entries[] = { { "g_tex2DTest", pDefaultSRV }, {nullptr, nullptr} };
+ ResourceMappingDesc ResourceMapping;
+ ResourceMapping.pEntries = Entries;
+ m_pRenderDevice->CreateResourceMapping( ResourceMapping, &m_pResourceMapping );
+ }
+ PipelineStateDesc PSODesc;
+ PSODesc.GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
+ PSODesc.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE;
+ PSODesc.GraphicsPipeline.BlendDesc.IndependentBlendEnable = False;
+ PSODesc.GraphicsPipeline.BlendDesc.RenderTargets[0].BlendEnable = False;
+ PSODesc.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM_SRGB;
+ PSODesc.GraphicsPipeline.NumRenderTargets = 1;
+ PSODesc.GraphicsPipeline.pVS = pVS;
+ PSODesc.GraphicsPipeline.pPS = pPS;
+
+ LayoutElement Elems[] =
+ {
+ LayoutElement( 0, 0, 3, Diligent::VT_FLOAT32, false, 0 ),
+ LayoutElement( 1, 0, 2, Diligent::VT_FLOAT32, false, sizeof( float ) * 3 )
+ };
+ PSODesc.GraphicsPipeline.InputLayout.LayoutElements = Elems;
+ PSODesc.GraphicsPipeline.InputLayout.NumElements = _countof( Elems );
+ pDevice->CreatePipelineState(PSODesc, &m_pPSO);
+
+ pVS->BindResources(m_pResourceMapping, 0);
+ pPS->BindResources(m_pResourceMapping, 0);
+}
+
+void TestTexturing::Draw()
+{
+ m_pDeviceContext->SetPipelineState(m_pPSO);
+ m_pDeviceContext->TransitionShaderResources(m_pPSO, nullptr);
+ m_pDeviceContext->CommitShaderResources(nullptr, 0);
+
+ IBuffer *pBuffs[] = {m_pVertexBuff};
+ Uint32 Strides[] = {sizeof(float)*5};
+ Uint32 Offsets[] = {0};
+ m_pDeviceContext->SetVertexBuffers( 0, 1, pBuffs, Strides, Offsets, SET_VERTEX_BUFFERS_FLAG_RESET );
+
+ Diligent::DrawAttribs DrawAttrs;
+ DrawAttrs.Topology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ DrawAttrs.NumVertices = 4; // Draw quad
+ m_pDeviceContext->Draw( DrawAttrs );
+}
diff --git a/Tests/TestApp/src/TestVPAndSR.cpp b/Tests/TestApp/src/TestVPAndSR.cpp
new file mode 100644
index 0000000..0f60bda
--- /dev/null
+++ b/Tests/TestApp/src/TestVPAndSR.cpp
@@ -0,0 +1,49 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "TestVPAndSR.h"
+#include "GraphicsUtilities.h"
+#include "ConvenienceFunctions.h"
+
+using namespace Diligent;
+
+TestVPAndSR::TestVPAndSR(IRenderDevice *pDevice, IDeviceContext *pContext )
+{
+ m_pRenderDevice = pDevice;
+ m_pDeviceContext = pContext;
+ m_pRenderScript = CreateRenderScriptFromFile( "VPAndSRTest.lua", pDevice, pContext, []( ScriptParser *pScriptParser )
+ {
+ Viewport VP(16.5, 24.25, 156.125, 381.625, 0.25, 0.75);
+ pScriptParser->SetGlobalVariable( "TestGlobalVP", VP );
+
+ Rect SR(10, 30, 200, 300);
+ pScriptParser->SetGlobalVariable( "TestGlobalSR", SR );
+ } );
+
+ m_pRenderScript->Run( m_pDeviceContext, "SetViewports" );
+ m_pRenderScript->Run( m_pDeviceContext, "SetScissorRects" );
+}
diff --git a/Tests/TestApp/src/UWP/TestAppUWP.cpp b/Tests/TestApp/src/UWP/TestAppUWP.cpp
new file mode 100644
index 0000000..a74a8de
--- /dev/null
+++ b/Tests/TestApp/src/UWP/TestAppUWP.cpp
@@ -0,0 +1,209 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+
+#include "TestApp.h"
+#include "RenderDeviceD3D12.h"
+#include "RenderDeviceD3D11.h"
+#include "SwapChainD3D12.h"
+#include "SwapChainD3D11.h"
+#include "RenderDeviceFactoryD3D11.h"
+#include "RenderDeviceFactoryD3D12.h"
+
+using namespace Diligent;
+
+class TestAppUWP final : public TestApp
+{
+public:
+ TestAppUWP()
+ {
+ m_DeviceType = DeviceType::D3D12;
+ }
+
+ virtual void OnWindowSizeChanged()override final
+ {
+ InitWindowSizeDependentResources();
+ }
+
+ virtual void Render()override
+ {
+ // Don't try to render anything before the first Update.
+ if (m_timer.GetFrameCount() == 0)
+ {
+ return;
+ }
+ TestApp::Render();
+ m_bFrameReady = true;
+ }
+
+ // Notifies the app that it is being suspended.
+ virtual void OnSuspending()override final
+ {
+ // TODO: Replace this with your app's suspending logic.
+
+ // Process lifetime management may terminate suspended apps at any time, so it is
+ // good practice to save any state that will allow the app to restart where it left off.
+
+ //m_sceneRenderer->SaveState();
+
+ // If your application uses video memory allocations that are easy to re-create,
+ // consider releasing that memory to make it available to other applications.
+ }
+
+ // Notifes the app that it is no longer suspended.
+ virtual void OnResuming()override final
+ {
+ // TODO: Replace this with your app's resuming logic.
+ }
+
+ // Notifies renderers that device resources need to be released.
+ virtual void OnDeviceRemoved()override final
+ {
+ // TODO: Save any necessary application or renderer state and release the renderer
+ // and its resources which are no longer valid.
+ //m_sceneRenderer->SaveState();
+ }
+
+ virtual void Present()override
+ {
+ m_pSwapChain->Present();
+
+ //// If the device was removed either by a disconnection or a driver upgrade, we
+ //// must recreate all device resources.
+ //if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
+ //{
+ // m_deviceRemoved = true;
+ //}
+ //else
+ //{
+ // DX::ThrowIfFailed(hr);
+ //}
+ }
+
+ virtual std::shared_ptr<DX::DeviceResources> InitDeviceResources()override
+ {
+ InitializeDiligentEngine(nullptr);
+
+ ID3D12Device *pd3d12Device = nullptr;
+ ID3D11Device *pd3d11Device = nullptr;
+ if (m_DeviceType == DeviceType::D3D12)
+ {
+ // Store pointers to the Direct3D 11.1 API device and immediate context.
+ RefCntAutoPtr<IRenderDeviceD3D12> pRenderDeviceD3D12(m_pDevice, IID_RenderDeviceD3D12);
+ pd3d12Device = pRenderDeviceD3D12->GetD3D12Device();
+ }
+ else if (m_DeviceType == DeviceType::D3D11)
+ {
+ RefCntAutoPtr<IRenderDeviceD3D11> pRenderDeviceD3D11(m_pDevice, IID_RenderDeviceD3D11);
+ pd3d11Device = pRenderDeviceD3D11->GetD3D11Device();
+ }
+ else
+ {
+ UNEXPECTED("Unexpected device type");
+ }
+ m_DeviceResources = std::make_shared<DX::DeviceResources>(pd3d11Device, pd3d12Device);
+
+ return m_DeviceResources;
+ }
+
+ virtual void InitWindowSizeDependentResources()override
+ {
+ m_DeviceResources->UpdateRenderTargetSize();
+ auto backBufferWidth = m_DeviceResources->GetBackBufferWidth();
+ auto backBufferHeight = m_DeviceResources->GetBackBufferHeight();
+
+ if (m_swapChain != nullptr)
+ {
+ m_swapChain.Reset();
+
+ // If the swap chain already exists, resize it.
+ m_pSwapChain->Resize(backBufferWidth, backBufferHeight);
+
+ #if 0
+ if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
+ {
+ // If the device was removed for any reason, a new device and swap chain will need to be created.
+ m_deviceRemoved = true;
+
+ // Do not continue execution of this method. DeviceResources will be destroyed and re-created.
+ return;
+ }
+ else
+ {
+ DX::ThrowIfFailed(hr);
+ }
+ #endif
+ }
+ else
+ {
+ //DXGI_SCALING scaling = DisplayMetrics::SupportHighResolutions ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH;
+ SwapChainDesc SCDesc;
+ SCDesc.Width = backBufferWidth;
+ SCDesc.Height = backBufferHeight;
+ SCDesc.ColorBufferFormat = TEX_FORMAT_RGBA8_UNORM_SRGB;
+ SCDesc.DepthBufferFormat = TEX_FORMAT_D32_FLOAT;
+ auto window = m_DeviceResources->GetWindow();
+ IDXGISwapChain3 *pDXGISwapChain3 = nullptr;
+ if (m_DeviceType == DeviceType::D3D12)
+ {
+ GetEngineFactoryD3D12()->CreateSwapChainD3D12(m_pDevice, m_pImmediateContext, SCDesc, reinterpret_cast<IUnknown*>(window), &m_pSwapChain);
+ }
+ else if (m_DeviceType == DeviceType::D3D11)
+ {
+ GetEngineFactoryD3D11()->CreateSwapChainD3D11(m_pDevice, m_pImmediateContext, SCDesc, reinterpret_cast<IUnknown*>(window), &m_pSwapChain);
+ }
+ else
+ UNEXPECTED("Unexpected device type");
+ }
+
+ IDXGISwapChain3 *pDXGISwapChain3 = nullptr;
+ if (m_DeviceType == DeviceType::D3D12)
+ {
+ RefCntAutoPtr<ISwapChainD3D12> pSwapChainD3D12(m_pSwapChain, IID_SwapChainD3D12);
+ pSwapChainD3D12->GetDXGISwapChain()->QueryInterface(__uuidof(pDXGISwapChain3), reinterpret_cast<void**>(&pDXGISwapChain3));
+ }
+ else if (m_DeviceType == DeviceType::D3D11)
+ {
+ RefCntAutoPtr<ISwapChainD3D11> pSwapChainD3D11(m_pSwapChain, IID_SwapChainD3D11);
+ pSwapChainD3D11->GetDXGISwapChain()->QueryInterface(__uuidof(pDXGISwapChain3), reinterpret_cast<void**>(&pDXGISwapChain3));
+ }
+ else
+ UNEXPECTED("Unexpected device type");
+ m_swapChain.Attach(pDXGISwapChain3);
+
+ m_DeviceResources->SetSwapChainRotation(m_swapChain.Get());
+ }
+
+ virtual void CreateRenderers()override
+ {
+ InitializeRenderers();
+ }
+
+private:
+ Microsoft::WRL::ComPtr<IDXGISwapChain3> m_swapChain;
+};
+
+
+NativeAppBase* CreateApplication()
+{
+ return new TestAppUWP;
+}
diff --git a/Tests/TestApp/src/VarSizeAllocationsManagerTest.cpp b/Tests/TestApp/src/VarSizeAllocationsManagerTest.cpp
new file mode 100644
index 0000000..5f50b59
--- /dev/null
+++ b/Tests/TestApp/src/VarSizeAllocationsManagerTest.cpp
@@ -0,0 +1,178 @@
+/* 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.
+ */
+
+// EngineSandbox.cpp : Defines the entry point for the application.
+//
+
+#include "pch.h"
+#include "VariableSizeGPUAllocationsManager.h"
+#include "DefaultRawMemoryAllocator.h"
+#include "DebugUtilities.h"
+
+using namespace Diligent;
+
+class VariableSizeAllocationsManagerTest
+{
+public:
+ VariableSizeAllocationsManagerTest();
+};
+
+static VariableSizeAllocationsManagerTest TheVariableSizeAllocationsManagerTest;
+
+VariableSizeAllocationsManagerTest::VariableSizeAllocationsManagerTest()
+{
+ auto &Allocator = DefaultRawMemoryAllocator::GetAllocator();
+ {
+ VariableSizeAllocationsManager ListMgr(128, Allocator);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 1);
+
+ auto o1 = ListMgr.Allocate(16);
+ VERIFY_EXPR(o1 == 0);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 1);
+
+ auto o2 = ListMgr.Allocate(32);
+ VERIFY_EXPR(o2 == 16);
+
+ auto o3 = ListMgr.Allocate(8);
+ VERIFY_EXPR(o3 == 48);
+
+ auto o4 = ListMgr.Allocate(16);
+ VERIFY_EXPR(o4 == 56);
+
+ auto o5 = ListMgr.Allocate(64);
+ VERIFY_EXPR(o5 == VariableSizeAllocationsManager::InvalidOffset);
+
+ o5 = ListMgr.Allocate(16);
+ VERIFY_EXPR(o5 == 72);
+
+ auto o6 = ListMgr.Allocate(8);
+ VERIFY_EXPR(o6 == 88);
+
+ auto o7 = ListMgr.Allocate(16);
+ VERIFY_EXPR(o7 == 96);
+
+ auto o8 = ListMgr.Allocate(8);
+ VERIFY_EXPR(o8 == 112);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 1);
+
+ auto o9 = ListMgr.Allocate(8);
+ VERIFY_EXPR(o9 == 120);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 0);
+
+ VERIFY_EXPR(ListMgr.IsFull());
+
+ ListMgr.Free(o6, 8);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 1);
+
+ ListMgr.Free(o8, 8);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 2);
+
+ ListMgr.Free(o9, 8);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 2);
+
+ auto o10 = ListMgr.Allocate(16);
+ VERIFY_EXPR(o10 == o8);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 1);
+
+ ListMgr.Free(o10, 16);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 2);
+
+ ListMgr.Free(o7, 16);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 1);
+
+ ListMgr.Free(o4, 16);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 2);
+
+ ListMgr.Free(o2, 32);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 3);
+
+ ListMgr.Free(o1, 16);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 3);
+
+ ListMgr.Free(o3, 8);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 2);
+
+ ListMgr.Free(o5, 16);
+ VERIFY_EXPR(ListMgr.DbgGetNumFreeBlocks() == 1);
+
+ VERIFY_EXPR(ListMgr.IsEmpty());
+ }
+
+ {
+ const auto NumAllocs = 6;
+ int NumPerms = 0;
+ size_t ReleaseOrder[NumAllocs];
+ for(size_t a=0; a < NumAllocs; ++a)
+ ReleaseOrder[a] = a;
+ do
+ {
+ ++NumPerms;
+ VariableSizeAllocationsManager ListMgr(NumAllocs*4, Allocator);
+ VariableSizeAllocationsManager::OffsetType allocs[NumAllocs];
+ for(size_t a=0; a < NumAllocs; ++a)
+ {
+ allocs[a] = ListMgr.Allocate(4);
+ VERIFY_EXPR(allocs[a] == a*4);
+ }
+ for(size_t a=0; a < NumAllocs; ++a)
+ {
+ ListMgr.Free(allocs[ReleaseOrder[a]], 4);
+ }
+ } while(std::next_permutation(std::begin(ReleaseOrder), std::end(ReleaseOrder)));
+ VERIFY_EXPR(NumPerms == 720);
+ }
+
+ {
+ VariableSizeGPUAllocationsManager ListMgr(128, Allocator);
+ VariableSizeGPUAllocationsManager::OffsetType off[16];
+ for(size_t o=0; o < _countof(off); ++o)
+ off[o] = ListMgr.Allocate(8);
+ VERIFY_EXPR(ListMgr.IsFull());
+
+ ListMgr.Free(off[1], 8, 0);
+ ListMgr.Free(off[5], 8, 0);
+ ListMgr.Free(off[4], 8, 0);
+ ListMgr.Free(off[3], 8, 0);
+
+ ListMgr.Free(off[10], 8, 1);
+ ListMgr.Free(off[13], 8, 1);
+ ListMgr.Free(off[2], 8, 1);
+ ListMgr.Free(off[8], 8, 1);
+
+ ListMgr.ReleaseStaleAllocations(1);
+
+ ListMgr.Free(off[14], 8, 2);
+ ListMgr.Free(off[7], 8, 2);
+ ListMgr.Free(off[0], 8, 2);
+ ListMgr.Free(off[9], 8, 2);
+
+ ListMgr.ReleaseStaleAllocations(2);
+
+ ListMgr.Free(off[12], 8, 1);
+ ListMgr.Free(off[15], 8, 1);
+ ListMgr.Free(off[6], 8, 1);
+ ListMgr.Free(off[11], 8, 1);
+
+ ListMgr.ReleaseStaleAllocations(3);
+ }
+}
diff --git a/Tests/TestApp/src/Win32/TestAppWin32.cpp b/Tests/TestApp/src/Win32/TestAppWin32.cpp
new file mode 100644
index 0000000..245c3eb
--- /dev/null
+++ b/Tests/TestApp/src/Win32/TestAppWin32.cpp
@@ -0,0 +1,39 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+
+#include "TestApp.h"
+
+class TestAppWin32 final : public TestApp
+{
+public:
+ virtual void OnWindowCreated(HWND hWnd, LONG WindowWidth, LONG WindowHeight)override final
+ {
+ InitializeDiligentEngine(hWnd);
+ InitializeRenderers();
+ }
+};
+
+NativeAppBase* CreateApplication()
+{
+ return new TestAppWin32;
+}
diff --git a/Tests/TestApp/src/pch.cpp b/Tests/TestApp/src/pch.cpp
new file mode 100644
index 0000000..b61be60
--- /dev/null
+++ b/Tests/TestApp/src/pch.cpp
@@ -0,0 +1,31 @@
+/* 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.
+ */
+
+// stdafx.cpp : source file that includes just the standard includes
+// EngineSandbox.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "pch.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file