diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2018-02-15 07:22:18 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2018-02-15 07:22:18 +0000 |
| commit | 5c9450e283d0889987e39ebd13b5a29c110d9e88 (patch) | |
| tree | fc8c9eb710106d57fe0f18816da9948d10ad7832 /Tests/TestApp/src | |
| parent | Fixed formatting of cmake files + some minor updates (diff) | |
| download | DiligentEngine-5c9450e283d0889987e39ebd13b5a29c110d9e88.tar.gz DiligentEngine-5c9450e283d0889987e39ebd13b5a29c110d9e88.zip | |
Added tests
Diffstat (limited to 'Tests/TestApp/src')
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 |
