summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsTools
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2017-11-13 02:54:50 +0000
committerEgor Yusov <egor.yusov@gmail.com>2017-11-13 02:54:50 +0000
commit8e24a0919d30f939140e776bc5e64bd77767e99c (patch)
treebfa1c37385cafe7d6c192ed0c8eb936aa828cb5a /Graphics/GraphicsTools
parentMerge from dev branch (diff)
downloadDiligentCore-8e24a0919d30f939140e776bc5e64bd77767e99c.tar.gz
DiligentCore-8e24a0919d30f939140e776bc5e64bd77767e99c.zip
Updated to Diligent Engine 2.1
Diffstat (limited to 'Graphics/GraphicsTools')
-rw-r--r--Graphics/GraphicsTools/build/Win32/GraphicsTools.vcxproj4
-rw-r--r--Graphics/GraphicsTools/build/Win32/GraphicsTools.vcxproj.filters3
-rw-r--r--Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.Shared.vcxitems13
-rw-r--r--Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.Shared.vcxitems.filters33
-rw-r--r--Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.props2
-rw-r--r--Graphics/GraphicsTools/include/CommonlyUsedStates.h76
-rw-r--r--Graphics/GraphicsTools/include/FreeBlockListManager.h276
-rw-r--r--Graphics/GraphicsTools/include/FreeBlockListManagerGPU.h85
-rw-r--r--Graphics/GraphicsTools/include/GraphicsUtilities.h34
-rw-r--r--Graphics/GraphicsTools/include/RingBuffer.h43
-rw-r--r--Graphics/GraphicsTools/include/ShaderMacroHelper.h49
-rw-r--r--Graphics/GraphicsTools/include/TextureUploader.h72
-rw-r--r--Graphics/GraphicsTools/include/TextureUploaderBase.h79
-rw-r--r--Graphics/GraphicsTools/include/TextureUploaderD3D11.h44
-rw-r--r--Graphics/GraphicsTools/include/TextureUploaderD3D12.h45
-rw-r--r--Graphics/GraphicsTools/include/TextureUploaderGL.h45
-rw-r--r--Graphics/GraphicsTools/include/VariableSizeGPUAllocationsManager.h20
-rw-r--r--Graphics/GraphicsTools/readme.md26
-rw-r--r--Graphics/GraphicsTools/src/BasicShaderSourceStreamFactory.cpp4
-rw-r--r--Graphics/GraphicsTools/src/GraphicsUtilities.cpp258
-rw-r--r--Graphics/GraphicsTools/src/TextureUploader.cpp52
-rw-r--r--Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp326
-rw-r--r--Graphics/GraphicsTools/src/TextureUploaderD3D12.cpp274
-rw-r--r--Graphics/GraphicsTools/src/TextureUploaderGL.cpp271
24 files changed, 1709 insertions, 425 deletions
diff --git a/Graphics/GraphicsTools/build/Win32/GraphicsTools.vcxproj b/Graphics/GraphicsTools/build/Win32/GraphicsTools.vcxproj
index a1020462..985d47c3 100644
--- a/Graphics/GraphicsTools/build/Win32/GraphicsTools.vcxproj
+++ b/Graphics/GraphicsTools/build/Win32/GraphicsTools.vcxproj
@@ -30,6 +30,7 @@
<ProjectGuid>{C6014499-0CF2-43EC-A773-A4E354FB2D74}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>GraphicsTools</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -147,9 +148,6 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
- <Text Include="ReadMe.txt" />
- </ItemGroup>
- <ItemGroup>
<None Include="jni\Android.mk" />
<None Include="jni\Application.mk" />
</ItemGroup>
diff --git a/Graphics/GraphicsTools/build/Win32/GraphicsTools.vcxproj.filters b/Graphics/GraphicsTools/build/Win32/GraphicsTools.vcxproj.filters
index 89d44e9e..ba635331 100644
--- a/Graphics/GraphicsTools/build/Win32/GraphicsTools.vcxproj.filters
+++ b/Graphics/GraphicsTools/build/Win32/GraphicsTools.vcxproj.filters
@@ -11,9 +11,6 @@
</Filter>
</ItemGroup>
<ItemGroup>
- <Text Include="ReadMe.txt" />
- </ItemGroup>
- <ItemGroup>
<None Include="jni\Android.mk">
<Filter>jni</Filter>
</None>
diff --git a/Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.Shared.vcxitems b/Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.Shared.vcxitems
index 050502cc..879867a4 100644
--- a/Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.Shared.vcxitems
+++ b/Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.Shared.vcxitems
@@ -18,6 +18,12 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\BasicShaderSourceStreamFactory.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\CommonlyUsedStates.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureUploader.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureUploaderBase.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureUploaderD3D11.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureUploaderD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureUploaderGL.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\VariableSizeAllocationsManager.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\VariableSizeGPUAllocationsManager.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\GraphicsUtilities.h" />
@@ -31,10 +37,17 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\TextureUploader.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\TextureUploaderD3D11.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\TextureUploaderD3D12.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\TextureUploaderGL.cpp" />
</ItemGroup>
<ItemGroup>
<Text Include="$(MSBuildThisFileDirectory)..\..\CMakeLists.txt">
<DeploymentContent>false</DeploymentContent>
</Text>
</ItemGroup>
+ <ItemGroup>
+ <None Include="$(MSBuildThisFileDirectory)..\..\readme.md" />
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.Shared.vcxitems.filters b/Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.Shared.vcxitems.filters
index 8d2bdcc1..99fee601 100644
--- a/Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.Shared.vcxitems.filters
+++ b/Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.Shared.vcxitems.filters
@@ -30,6 +30,24 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\VariableSizeGPUAllocationsManager.h">
<Filter>include</Filter>
</ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\CommonlyUsedStates.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureUploaderD3D12.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureUploader.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureUploaderD3D11.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureUploaderBase.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureUploaderGL.h">
+ <Filter>include</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\pch.cpp">
@@ -41,8 +59,23 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\GraphicsUtilities.cpp">
<Filter>src</Filter>
</ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\TextureUploaderD3D11.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\TextureUploaderD3D12.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\TextureUploader.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\TextureUploaderGL.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="$(MSBuildThisFileDirectory)..\..\CMakeLists.txt" />
</ItemGroup>
+ <ItemGroup>
+ <None Include="$(MSBuildThisFileDirectory)..\..\readme.md" />
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.props b/Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.props
index 4da87146..c2ad8f8a 100644
--- a/Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.props
+++ b/Graphics/GraphicsTools/build/Windows.Shared/GraphicsTools.props
@@ -6,7 +6,7 @@
<GraphicsRoot>..\..\..</GraphicsRoot>
</PropertyGroup>
<PropertyGroup>
- <IncludePath>$(GraphicsRoot)\GraphicsTools\include;$(GraphicsRoot)\GraphicsEngine\interface;$(GraphicsRoot)\TextureLoader\interface;$(EngineRoot)\Common\include;$(EngineRoot)\Common\interface;$(EngineRoot)\Platforms\interface;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(IncludePath)</IncludePath>
+ <IncludePath>$(GraphicsRoot)\GraphicsTools\include;$(GraphicsRoot)\GraphicsEngine\interface;$(GraphicsRoot)\GraphicsEngineD3D11\interface;$(GraphicsRoot)\GraphicsEngineD3D12\interface;$(GraphicsRoot)\GraphicsEngineD3DBase\include;$(GraphicsRoot)\GraphicsEngineOpenGL\interface;$(GraphicsRoot)\TextureLoader\interface;$(EngineRoot)\Common\include;$(EngineRoot)\Common\interface;$(EngineRoot)\Platforms\interface;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup />
<ItemGroup>
diff --git a/Graphics/GraphicsTools/include/CommonlyUsedStates.h b/Graphics/GraphicsTools/include/CommonlyUsedStates.h
new file mode 100644
index 00000000..899a0b15
--- /dev/null
+++ b/Graphics/GraphicsTools/include/CommonlyUsedStates.h
@@ -0,0 +1,76 @@
+/* Copyright 2015-2017 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Defines graphics engine utilities
+
+#include "GraphicsTypes.h"
+#include "DepthStencilState.h"
+#include "BlendState.h"
+#include "RasterizerState.h"
+#include "Sampler.h"
+
+namespace Diligent
+{
+ // Common depth-stencil states
+ const DepthStencilStateDesc DSS_DisableDepth(False, False);
+
+ // Common rasterizer states
+ const RasterizerStateDesc RS_SolidFillNoCull(FILL_MODE_SOLID, CULL_MODE_NONE);
+
+ const RasterizerStateDesc RS_WireFillNoCull(FILL_MODE_WIREFRAME, CULL_MODE_NONE, false, 1, 0.f, 1.f);
+
+
+ // Common sampler states
+ const SamplerDesc Sam_LinearClamp(FILTER_TYPE_LINEAR, FILTER_TYPE_LINEAR, FILTER_TYPE_LINEAR,
+ TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP);
+
+ const SamplerDesc Sam_PointClamp(FILTER_TYPE_POINT, FILTER_TYPE_POINT, FILTER_TYPE_POINT,
+ TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP);
+
+ const SamplerDesc Sam_LinearMirror(FILTER_TYPE_LINEAR, FILTER_TYPE_LINEAR, FILTER_TYPE_LINEAR,
+ TEXTURE_ADDRESS_MIRROR, TEXTURE_ADDRESS_MIRROR, TEXTURE_ADDRESS_MIRROR);
+
+ const SamplerDesc Sam_PointWrap(FILTER_TYPE_POINT, FILTER_TYPE_POINT, FILTER_TYPE_POINT,
+ TEXTURE_ADDRESS_WRAP, TEXTURE_ADDRESS_WRAP, TEXTURE_ADDRESS_WRAP);
+
+ const SamplerDesc Sam_LinearWrap(FILTER_TYPE_LINEAR, FILTER_TYPE_LINEAR, FILTER_TYPE_LINEAR,
+ TEXTURE_ADDRESS_WRAP, TEXTURE_ADDRESS_WRAP, TEXTURE_ADDRESS_WRAP);
+
+ const SamplerDesc Sam_Aniso2xClamp(FILTER_TYPE_ANISOTROPIC, FILTER_TYPE_ANISOTROPIC, FILTER_TYPE_ANISOTROPIC,
+ TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, 0.f, 2);
+
+ const SamplerDesc Sam_Aniso4xClamp(FILTER_TYPE_ANISOTROPIC, FILTER_TYPE_ANISOTROPIC, FILTER_TYPE_ANISOTROPIC,
+ TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, 0.f, 4);
+
+ const SamplerDesc Sam_Aniso8xClamp(FILTER_TYPE_ANISOTROPIC, FILTER_TYPE_ANISOTROPIC, FILTER_TYPE_ANISOTROPIC,
+ TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, 0.f, 8);
+
+ const SamplerDesc Sam_Aniso16xClamp(FILTER_TYPE_ANISOTROPIC, FILTER_TYPE_ANISOTROPIC, FILTER_TYPE_ANISOTROPIC,
+ TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, 0.f, 16);
+
+ const SamplerDesc Sam_Aniso8xWrap(FILTER_TYPE_ANISOTROPIC, FILTER_TYPE_ANISOTROPIC, FILTER_TYPE_ANISOTROPIC,
+ TEXTURE_ADDRESS_WRAP, TEXTURE_ADDRESS_WRAP, TEXTURE_ADDRESS_WRAP, 0.f, 8);
+}
diff --git a/Graphics/GraphicsTools/include/FreeBlockListManager.h b/Graphics/GraphicsTools/include/FreeBlockListManager.h
deleted file mode 100644
index 7eb9d931..00000000
--- a/Graphics/GraphicsTools/include/FreeBlockListManager.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/* Copyright 2015-2016 Egor Yusov
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
- *
- * In no event and under no legal theory, whether in tort (including negligence),
- * contract, or otherwise, unless required by applicable law (such as deliberate
- * and grossly negligent acts) or agreed to in writing, shall any Contributor be
- * liable for any damages, including any direct, indirect, special, incidental,
- * or consequential damages of any character arising as a result of this License or
- * out of the use or inability to use the software (including but not limited to damages
- * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
- * all other commercial damages or losses), even if such Contributor has been advised
- * of the possibility of such damages.
- */
-
-#pragma once
-
-#include <map>
-#include "MemoryAllocator.h"
-#include "FixedBlockMemoryAllocator.h"
-#include "STDAllocator.h"
-#include "DebugUtilities.h"
-
-namespace Diligent
-{
- class FreeBlockListManager
- {
- public:
- typedef size_t OffsetType;
- typedef std::pair<Uint64,OffsetType> FrameNumOffsetPair;
-
- struct FreeBlockInfo;
- typedef std::map<OffsetType,
- FreeBlockInfo,
- std::less<OffsetType>, // Standard ordering
- STDAllocatorRawMem<std::pair<OffsetType, FreeBlockInfo>> // Raw memory allocator
- > TFreeBlocksByOffsetMap;
- typedef std::multimap<OffsetType,
- TFreeBlocksByOffsetMap::iterator,
- std::less<OffsetType>, // Standard ordering
- STDAllocatorRawMem<std::pair<OffsetType, TFreeBlocksByOffsetMap::iterator>> // Raw memory allocator
- > TFreeBlocksBySizeMap;
-
- struct FreeBlockInfo
- {
- // Block size (no reserved space)
- OffsetType Size;
-
- // Iterator referencing this block in the multimap sorted by the block size
- TFreeBlocksBySizeMap::iterator OrderBySizeIt;
-
- FreeBlockInfo(OffsetType _Size) : Size(_Size){}
- };
-
- static const OffsetType InvalidOffset = static_cast<OffsetType>(-1);
-
- FreeBlockListManager(OffsetType MaxSize, IMemoryAllocator &Allocator) :
- m_MaxSize(MaxSize),
- m_FreeSize(MaxSize),
- m_FreeBlocks( STD_ALLOCATOR_RAW_MEM(TFreeBlocksByOffsetMap::value_type, Allocator, "Allocator for std::map<OffsetType, FreeBlockInfo>") ),
- m_FreeBlocksBySize( STD_ALLOCATOR_RAW_MEM(TFreeBlocksBySizeMap::value_type, Allocator, "multimap<OffsetType, TFreeBlocksByOffsetMap::iterator>") )
- {
- AddNewBlock(0, m_MaxSize);
-
-#ifdef _DEBUG
- DbgVerifyList();
-#endif
- }
-
- ~FreeBlockListManager()
- {
- if( !m_FreeBlocks.empty() || !m_FreeBlocksBySize.empty() )
- {
- VERIFY(m_FreeBlocks.size() == 1, "Single free block is expected");
- VERIFY(m_FreeBlocks.begin()->first == 0, "Head chunk offset is expected to be 0");
- VERIFY(m_FreeBlocks.begin()->second.Size == m_MaxSize, "Head chunk size is expected to be ", m_MaxSize);
-
- VERIFY(m_FreeBlocksBySize.size() == 1, "Single free block is expected");
- VERIFY(m_FreeBlocksBySize.begin()->first == m_MaxSize, "Head chunk size is expected to be ", m_MaxSize);
- VERIFY(m_FreeBlocksBySize.begin()->second == m_FreeBlocks.begin(), "Incorrect first block");
- }
- }
-
- FreeBlockListManager(FreeBlockListManager&& rhs) :
- m_FreeBlocks(std::move(rhs.m_FreeBlocks)),
- m_FreeBlocksBySize(std::move(rhs.m_FreeBlocksBySize)),
- m_MaxSize(rhs.m_MaxSize),
- m_FreeSize(rhs.m_FreeSize)
- {
- rhs.m_MaxSize = 0;
- rhs.m_FreeSize = 0;
- }
- FreeBlockListManager& operator = (FreeBlockListManager&& rhs) = default;
- FreeBlockListManager(const FreeBlockListManager&) = delete;
- FreeBlockListManager& operator = (const FreeBlockListManager&) = delete;
-
- OffsetType Allocate(OffsetType Size)
- {
- VERIFY_EXPR(Size != 0);
- if(m_FreeSize < Size)
- return InvalidOffset;
-
- // Get the first block that is >= Size
- auto SmallestBlockItIt = m_FreeBlocksBySize.lower_bound(Size);
- if(SmallestBlockItIt == m_FreeBlocksBySize.end())
- return InvalidOffset;
-
- auto SmallestBlockIt = SmallestBlockItIt->second;
- VERIFY_EXPR(Size <= SmallestBlockIt->second.Size);
-
- auto Offset = SmallestBlockIt->first;
- auto NewOffset = Offset + Size;
- auto NewSize = SmallestBlockIt->second.Size - Size;
- VERIFY_EXPR(SmallestBlockItIt == SmallestBlockIt->second.OrderBySizeIt);
- m_FreeBlocksBySize.erase(SmallestBlockItIt);
- m_FreeBlocks.erase(SmallestBlockIt);
- if (NewSize > 0)
- {
- AddNewBlock(NewOffset, NewSize);
- }
-
- m_FreeSize -= Size;
-
-#ifdef _DEBUG
- DbgVerifyList();
-#endif
- return Offset;
- }
-
- void Free(OffsetType Offset, OffsetType Size)
- {
- VERIFY_EXPR(Offset+Size <= m_MaxSize);
-
- auto NextBlockIt = m_FreeBlocks.upper_bound(Offset); // First element >
-#ifdef _DEBUG
- {
- auto LowBnd = m_FreeBlocks.lower_bound(Offset); // First element >=
- // Since zero-size allocations are not allowed, lower bound must always be equal upper bound
- VERIFY_EXPR(LowBnd == NextBlockIt);
- }
-#endif
- VERIFY_EXPR(NextBlockIt == m_FreeBlocks.end() || Offset <= NextBlockIt->first + NextBlockIt->second.Size);
- auto PrevBlockIt = NextBlockIt;
- if(PrevBlockIt != m_FreeBlocks.begin())
- {
- --PrevBlockIt;
- VERIFY_EXPR(Offset >= PrevBlockIt->first + PrevBlockIt->second.Size);
- }
- else
- PrevBlockIt = m_FreeBlocks.end();
-
- OffsetType NewSize, NewOffset;
- if(PrevBlockIt != m_FreeBlocks.end() && Offset == PrevBlockIt->first + PrevBlockIt->second.Size)
- {
- // PrevBlock.Offset Offset
- // | |
- // |<-----PrevBlock.Size----->|<------Size-------->|
- //
- NewSize = PrevBlockIt->second.Size + Size;
- NewOffset = PrevBlockIt->first;
-
- if (NextBlockIt != m_FreeBlocks.end() && Offset + Size == NextBlockIt->first)
- {
- // PrevBlock.Offset Offset NextBlock.Offset
- // | | |
- // |<-----PrevBlock.Size----->|<------Size-------->|<-----NextBlock.Size----->|
- //
- NewSize += NextBlockIt->second.Size;
- m_FreeBlocksBySize.erase(PrevBlockIt->second.OrderBySizeIt);
- m_FreeBlocksBySize.erase(NextBlockIt->second.OrderBySizeIt);
- ++NextBlockIt;
- m_FreeBlocks.erase(PrevBlockIt, NextBlockIt);
- }
- else
- {
- // PrevBlock.Offset Offset NextBlock.Offset
- // | | |
- // |<-----PrevBlock.Size----->|<------Size-------->| ~ ~ ~ |<-----NextBlock.Size----->|
- //
- m_FreeBlocksBySize.erase(PrevBlockIt->second.OrderBySizeIt);
- m_FreeBlocks.erase(PrevBlockIt);
- }
- }
- else if (NextBlockIt != m_FreeBlocks.end() && Offset + Size == NextBlockIt->first)
- {
- // PrevBlock.Offset Offset NextBlock.Offset
- // | | |
- // |<-----PrevBlock.Size----->| ~ ~ ~ |<------Size-------->|<-----NextBlock.Size----->|
- //
- NewSize = Size + NextBlockIt->second.Size;
- NewOffset = Offset;
- m_FreeBlocksBySize.erase(NextBlockIt->second.OrderBySizeIt);
- m_FreeBlocks.erase(NextBlockIt);
- }
- else
- {
- // PrevBlock.Offset Offset NextBlock.Offset
- // | | |
- // |<-----PrevBlock.Size----->| ~ ~ ~ |<------Size-------->| ~ ~ ~ |<-----NextBlock.Size----->|
- //
- NewSize = Size;
- NewOffset = Offset;
- }
-
- AddNewBlock(NewOffset, NewSize);
-
- m_FreeSize += Size;
-#ifdef _DEBUG
- DbgVerifyList();
-#endif
- }
-
- OffsetType GetMaxSize()const{return m_MaxSize;}
- bool IsFull()const{ return m_FreeSize==0; };
- bool IsEmpty()const{ return m_FreeSize==m_MaxSize; };
- OffsetType GetFreeSize()const{return m_FreeSize;}
-
-#ifdef _DEBUG
- size_t DbgGetNumFreeBlocks()const{return m_FreeBlocks.size();}
-#endif
-
- private:
- void AddNewBlock(OffsetType Offset, OffsetType Size)
- {
- auto NewBlockIt = m_FreeBlocks.emplace(Offset, Size);
- VERIFY_EXPR(NewBlockIt.second);
- auto OrderIt = m_FreeBlocksBySize.emplace(Size, NewBlockIt.first);
- NewBlockIt.first->second.OrderBySizeIt = OrderIt;
- }
-
-
-#ifdef _DEBUG
- void DbgVerifyList()
- {
- OffsetType TotalFreeSize = 0;
-
- auto BlockIt = m_FreeBlocks.begin();
- auto PrevBlockIt = m_FreeBlocks.end();
- VERIFY_EXPR(m_FreeBlocks.size() == m_FreeBlocksBySize.size());
- while (BlockIt != m_FreeBlocks.end())
- {
- VERIFY_EXPR(BlockIt->first >= 0 && BlockIt->first + BlockIt->second.Size <= m_MaxSize);
- VERIFY_EXPR(BlockIt == BlockIt->second.OrderBySizeIt->second);
- VERIFY(PrevBlockIt == m_FreeBlocks.end() || BlockIt->first > PrevBlockIt->first + PrevBlockIt->second.Size, "Adjoint blocks detected" );
- TotalFreeSize += BlockIt->second.Size;
-
- PrevBlockIt = BlockIt;
- ++BlockIt;
- }
-
- auto OrderIt = m_FreeBlocksBySize.begin();
- while (OrderIt != m_FreeBlocksBySize.end())
- {
- VERIFY_EXPR(OrderIt->first == OrderIt->second->second.Size);
- ++OrderIt;
- }
-
- VERIFY_EXPR(TotalFreeSize == m_FreeSize);
- }
-#endif
-
- TFreeBlocksByOffsetMap m_FreeBlocks;
- TFreeBlocksBySizeMap m_FreeBlocksBySize;
-
- OffsetType m_MaxSize = 0;
- OffsetType m_FreeSize = 0;
- };
-}
diff --git a/Graphics/GraphicsTools/include/FreeBlockListManagerGPU.h b/Graphics/GraphicsTools/include/FreeBlockListManagerGPU.h
deleted file mode 100644
index f2961bd3..00000000
--- a/Graphics/GraphicsTools/include/FreeBlockListManagerGPU.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright 2015-2016 Egor Yusov
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
- *
- * In no event and under no legal theory, whether in tort (including negligence),
- * contract, or otherwise, unless required by applicable law (such as deliberate
- * and grossly negligent acts) or agreed to in writing, shall any Contributor be
- * liable for any damages, including any direct, indirect, special, incidental,
- * or consequential damages of any character arising as a result of this License or
- * out of the use or inability to use the software (including but not limited to damages
- * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
- * all other commercial damages or losses), even if such Contributor has been advised
- * of the possibility of such damages.
- */
-
-#pragma once
-
-#include <deque>
-#include "FreeBlockListManager.h"
-#include "STDAllocator.h"
-
-namespace Diligent
-{
- class FreeBlockListManagerGPU : public FreeBlockListManager
- {
- private:
- struct FreedAllocationInfo
- {
- OffsetType Offset;
- OffsetType Size;
- Uint64 FrameNumber;
- FreedAllocationInfo(OffsetType _Offset, OffsetType _Size, Uint64 _FrameNumber) :
- Offset(_Offset), Size(_Size), FrameNumber(_FrameNumber)
- {}
- };
-
- public:
- FreeBlockListManagerGPU(OffsetType MaxSize, IMemoryAllocator &Allocator) :
- FreeBlockListManager(MaxSize, Allocator),
- m_StaleAllocations(0, FreedAllocationInfo(0,0,0), STD_ALLOCATOR_RAW_MEM(FreedAllocationInfo, Allocator, "Allocator for deque< FreedAllocationInfo>" ))
- {}
-
- ~FreeBlockListManagerGPU()
- {
- VERIFY(m_StaleAllocations.empty(), "Not all stale allocations released");
- }
-
- // = default causes compiler error when instantiating std::vector::emplace_back() in Visual Studio 2015 (Version 14.0.23107.0 D14REL)
- FreeBlockListManagerGPU(FreeBlockListManagerGPU&& rhs) :
- FreeBlockListManager(std::move(rhs)),
- m_StaleAllocations(std::move(rhs.m_StaleAllocations))
- {
- }
-
- FreeBlockListManagerGPU& operator = (FreeBlockListManagerGPU&& rhs) = default;
- FreeBlockListManagerGPU(const FreeBlockListManagerGPU&) = delete;
- FreeBlockListManagerGPU& operator = (const FreeBlockListManagerGPU&) = delete;
-
- void Free(OffsetType Offset, OffsetType Size, Uint64 FrameNumber)
- {
- m_StaleAllocations.emplace_back(Offset, Size, FrameNumber);
- }
-
- void ReleaseCompletedFrames(Uint64 NumCompletedFrames)
- {
- while(!m_StaleAllocations.empty() && m_StaleAllocations.front().FrameNumber < NumCompletedFrames)
- {
- auto &OldestAllocation = m_StaleAllocations.front();
- FreeBlockListManager::Free(OldestAllocation.Offset, OldestAllocation.Size);
- m_StaleAllocations.pop_front();
- }
- }
-
- private:
- std::deque< FreedAllocationInfo, STDAllocatorRawMem<FreedAllocationInfo> > m_StaleAllocations;
- };
-}
diff --git a/Graphics/GraphicsTools/include/GraphicsUtilities.h b/Graphics/GraphicsTools/include/GraphicsUtilities.h
index f13684fd..a0cc2247 100644
--- a/Graphics/GraphicsTools/include/GraphicsUtilities.h
+++ b/Graphics/GraphicsTools/include/GraphicsUtilities.h
@@ -131,6 +131,36 @@ const Char* GetValueTypeString( VALUE_TYPE Val );
/// format attributes.
const TextureFormatAttribs& GetTextureFormatAttribs(TEXTURE_FORMAT Format);
+/// Returns the default format for a specified texture view type
+
+/// The default view is defined as follows:
+/// * For a fully qualified texture format, the SRV/RTV/UAV view format is the same as texture format;
+/// DSV format, if avaialble, is adjusted accrodingly (R32_FLOAT -> D32_FLOAT)
+/// * For 32-bit typeless formats, default view is XXXX32_FLOAT (where XXXX are the actual format components)\n
+/// * For 16-bit typeless formats, default view is XXXX16_FLOAT (where XXXX are the actual format components)\n
+/// ** R16_TYPELESS is special. If BIND_DEPTH_STENCIL flag is set, it is translated to R16_UNORM/D16_UNORM;
+/// otherwise it is translated to R16_FLOAT.
+/// * For 8-bit typeless formats, default view is XXXX8_UNORM (where XXXX are the actual format components)\n
+/// * sRGB is always chosen if it is available (RGBA8_UNORM_SRGB, TEX_FORMAT_BC1_UNORM_SRGB, etc.)
+/// * For combined depth-stencil formats, SRV format references depth component (R24_UNORM_X8_TYPELESS for D24S8 formats, and
+/// R32_FLOAT_X8X24_TYPELESS for D32S8X24 formats)
+/// * For compressed formats, only SRV format is defined
+///
+/// \param [in] Format - texture format, for which the view format is requested
+/// \param [in] ViewType - texture view type
+/// \param [in] BindFlags - texture bind flags
+/// \return texture view type format
+TEXTURE_FORMAT GetDefaultTextureViewFormat(TEXTURE_FORMAT TextureFormat, TEXTURE_VIEW_TYPE ViewType, Uint32 BindFlags);
+
+/// Returns the default format for a specified texture view type
+
+/// \param [in] TexDesc - texture description
+/// \param [in] ViewType - texture view type
+/// \return texture view type format
+inline TEXTURE_FORMAT GetDefaultTextureViewFormat(const TextureDesc &TexDesc, TEXTURE_VIEW_TYPE ViewType)
+{
+ return GetDefaultTextureViewFormat(TexDesc.Format, ViewType, TexDesc.BindFlags);
+}
/// Returns the literal name of a texture view type. For instance,
/// for a shader resource view, "TEXTURE_VIEW_SHADER_RESOURCE" will be returned.
@@ -225,6 +255,6 @@ Uint32 ComputeMipLevelsCount( Uint32 Width );
Uint32 ComputeMipLevelsCount( Uint32 Width, Uint32 Height );
Uint32 ComputeMipLevelsCount( Uint32 Width, Uint32 Height, Uint32 Depth );
-void CreateUniformBuffer( IRenderDevice *pDevice, Uint32 Size, IBuffer **ppBuffer, USAGE Usage = USAGE_DYNAMIC, Uint32 BindFlag = BIND_UNIFORM_BUFFER, Uint32 CPUAccessFlags = CPU_ACCESS_WRITE );
-
+void CreateUniformBuffer( IRenderDevice *pDevice, Uint32 Size, const Char *Name, IBuffer **ppBuffer, USAGE Usage = USAGE_DYNAMIC, Uint32 BindFlag = BIND_UNIFORM_BUFFER, Uint32 CPUAccessFlags = CPU_ACCESS_WRITE );
+void GenerateCheckerBoardPattern(Uint32 Width, Uint32 Height, TEXTURE_FORMAT Fmt, Uint32 HorzCells, Uint32 VertCells, Uint8 *pData, Uint32 StrideInBytes );
}
diff --git a/Graphics/GraphicsTools/include/RingBuffer.h b/Graphics/GraphicsTools/include/RingBuffer.h
index 8c4119ac..e053eefe 100644
--- a/Graphics/GraphicsTools/include/RingBuffer.h
+++ b/Graphics/GraphicsTools/include/RingBuffer.h
@@ -41,23 +41,26 @@ namespace Diligent
typedef size_t OffsetType;
struct FrameTailAttribs
{
- FrameTailAttribs(Uint64 fn, OffsetType off, OffsetType sz) :
- FrameNum(fn),
+ FrameTailAttribs(Uint64 fv, OffsetType off, OffsetType sz) :
+ FenceValue(fv),
Offset(off),
Size(sz)
{}
- Uint64 FrameNum;
+
+ // Fence value associated with the command list in which
+ // the allocation could have been referenced last time
+ Uint64 FenceValue;
OffsetType Offset;
OffsetType Size;
};
static const OffsetType InvalidOffset = static_cast<OffsetType>(-1);
- RingBuffer(OffsetType MaxSize, IMemoryAllocator &Allocator) :
+ RingBuffer(OffsetType MaxSize, IMemoryAllocator &Allocator)noexcept :
m_CompletedFrameTails(0, FrameTailAttribs(0,0,0), STD_ALLOCATOR_RAW_MEM(FrameTailAttribs, Allocator, "Allocator for vector<FrameNumOffsetPair>" )),
m_MaxSize(MaxSize)
{}
- RingBuffer(RingBuffer&& rhs) :
+ RingBuffer(RingBuffer&& rhs)noexcept :
m_CompletedFrameTails(std::move(rhs.m_CompletedFrameTails)),
m_Head(rhs.m_Head),
m_Tail(rhs.m_Tail),
@@ -72,12 +75,7 @@ namespace Diligent
rhs.m_CurrFrameSize = 0;
}
- ~RingBuffer()
- {
- VERIFY(m_UsedSize==0, "All space in the ring buffer must be released")
- }
-
- RingBuffer& operator = (RingBuffer&& rhs)
+ RingBuffer& operator = (RingBuffer&& rhs)noexcept
{
m_CompletedFrameTails = std::move(rhs.m_CompletedFrameTails);
m_Head = rhs.m_Head;
@@ -98,6 +96,11 @@ namespace Diligent
RingBuffer(const RingBuffer&) = delete;
RingBuffer& operator = (const RingBuffer&) = delete;
+ ~RingBuffer()
+ {
+ VERIFY(m_UsedSize==0, "All space in the ring buffer must be released")
+ }
+
OffsetType Allocate(OffsetType Size)
{
if(IsFull())
@@ -147,24 +150,24 @@ namespace Diligent
return InvalidOffset;
}
- // FrameNum is the number of the frame (or command list) in which the tail
+ // FenceValue is the fence value associated with the command list in which the tail
// could have been referenced last time
// See http://diligentgraphics.com/diligent-engine/architecture/d3d12/managing-resource-lifetimes/
- void FinishCurrentFrame(Uint64 FrameNum)
+ void FinishCurrentFrame(Uint64 FenceValue)
{
- m_CompletedFrameTails.emplace_back(FrameNum, m_Tail, m_CurrFrameSize);
+ m_CompletedFrameTails.emplace_back(FenceValue, m_Tail, m_CurrFrameSize);
m_CurrFrameSize = 0;
}
- // NumCompletedFrames is the number of completed frames (or command lists)
+ // CompletedFenceValue indicates GPU progress
// See http://diligentgraphics.com/diligent-engine/architecture/d3d12/managing-resource-lifetimes/
- void ReleaseCompletedFrames(Uint64 NumCompletedFrames)
+ void ReleaseCompletedFrames(Uint64 CompletedFenceValue)
{
- // Command list is completed when its number is strictly less than the number of completed frames
- while(!m_CompletedFrameTails.empty() && m_CompletedFrameTails.front().FrameNum < NumCompletedFrames)
+ // We can release all tails whose associated fence value is less than or equal to CompletedFenceValue
+ while(!m_CompletedFrameTails.empty() && m_CompletedFrameTails.front().FenceValue <= CompletedFenceValue)
{
const auto &OldestFrameTail = m_CompletedFrameTails.front();
- VERIFY_EXPR(OldestFrameTail.Size <= m_MaxSize);
+ VERIFY_EXPR(OldestFrameTail.Size <= m_UsedSize);
m_UsedSize -= OldestFrameTail.Size;
m_Head = OldestFrameTail.Offset;
m_CompletedFrameTails.pop_front();
@@ -177,7 +180,7 @@ namespace Diligent
OffsetType GetUsedSize()const{return m_UsedSize;}
private:
- // Consider the following scenario for 1024 buffer:
+ // Consider the following scenario for a 1024-byte buffer:
// Allocate(512)
//
// h t m
diff --git a/Graphics/GraphicsTools/include/ShaderMacroHelper.h b/Graphics/GraphicsTools/include/ShaderMacroHelper.h
index 1beec624..15a2137b 100644
--- a/Graphics/GraphicsTools/include/ShaderMacroHelper.h
+++ b/Graphics/GraphicsTools/include/ShaderMacroHelper.h
@@ -36,6 +36,7 @@
// assume any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
//--------------------------------------------------------------------------------------
+#pragma once
#include <set>
#include <vector>
@@ -51,12 +52,10 @@ namespace Diligent
class ShaderMacroHelper
{
public:
- ShaderMacroHelper() : m_bIsFinalized(false) {}
template<typename DefintionType>
void AddShaderMacro( const Diligent::Char* Name, DefintionType Definition )
{
- assert( !m_bIsFinalized );
std::ostringstream ss;
ss << Definition;
AddShaderMacro<const Diligent::Char*>( Name, ss.str().c_str() );
@@ -64,49 +63,61 @@ public:
void Finalize()
{
- ShaderMacro LastMacro = {NULL, NULL};
- m_Macros.push_back(LastMacro);
- m_bIsFinalized = true;
+ if (!m_bIsFinalized)
+ {
+ m_Macros.emplace_back(nullptr, nullptr);
+ m_bIsFinalized = true;
+ }
}
+ void Reopen()
+ {
+ if (m_bIsFinalized)
+ {
+ VERIFY_EXPR(m_Macros.size() > 0 && m_Macros.back().Name == nullptr && m_Macros.back().Definition == nullptr);
+ m_Macros.pop_back();
+ m_bIsFinalized = false;
+ }
+ }
+
+ void Clear()
+ {
+ m_Macros.clear();
+ m_DefinitionsPool.clear();
+ m_bIsFinalized = false;
+ }
+
operator const ShaderMacro* ()
{
- assert( !m_Macros.size() || m_bIsFinalized );
- if( m_Macros.size() && !m_bIsFinalized )
+ if (m_Macros.size() > 0 && !m_bIsFinalized)
Finalize();
- return m_Macros.size() ? &m_Macros[0] : NULL;
+ return m_Macros.size() ? m_Macros.data() : nullptr;
}
private:
std::vector< ShaderMacro > m_Macros;
- std::set< std::string > m_DefinitionsPull;
- bool m_bIsFinalized;
+ std::set< std::string > m_DefinitionsPool;
+ bool m_bIsFinalized = false;
};
template<>
inline void ShaderMacroHelper::AddShaderMacro( const Diligent::Char* Name, const Diligent::Char* Definition )
{
- VERIFY_EXPR( !m_bIsFinalized );
- ShaderMacro NewMacro =
- {
- Name,
- m_DefinitionsPull.insert(Definition).first->c_str()
- };
- m_Macros.push_back(NewMacro);
+ Reopen();
+ auto *PooledDefinition = m_DefinitionsPool.insert(Definition).first->c_str();
+ m_Macros.emplace_back(Name, PooledDefinition);
}
template<>
inline void ShaderMacroHelper::AddShaderMacro( const Diligent::Char* Name, bool Definition )
{
- assert( !m_bIsFinalized );
AddShaderMacro( Name, Definition ? "1" : "0");
}
template<>
inline void ShaderMacroHelper::AddShaderMacro( const Diligent::Char* Name, float Definition )
{
- assert( !m_bIsFinalized );
std::ostringstream ss;
// Make sure that when floating point represents integer, it is still
diff --git a/Graphics/GraphicsTools/include/TextureUploader.h b/Graphics/GraphicsTools/include/TextureUploader.h
new file mode 100644
index 00000000..9f528ad3
--- /dev/null
+++ b/Graphics/GraphicsTools/include/TextureUploader.h
@@ -0,0 +1,72 @@
+/* Copyright 2015-2017 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "RenderDevice.h"
+#include "DeviceContext.h"
+
+namespace Diligent
+{
+ struct UploadBufferDesc
+ {
+ Uint32 Width = 0;
+ Uint32 Height = 0;
+ Uint32 Depth = 1;
+ TEXTURE_FORMAT Format = TEX_FORMAT_UNKNOWN;
+
+ bool operator == (const UploadBufferDesc &rhs) const
+ {
+ return Width == rhs.Width &&
+ Height == rhs.Height &&
+ Depth == rhs.Depth &&
+ Format == rhs.Format;
+ }
+ };
+
+ class IUploadBuffer : public IObject
+ {
+ public:
+ virtual void WaitForCopyScheduled() = 0;
+ virtual void* GetDataPtr() = 0;
+ virtual size_t GetRowStride() const = 0;
+ virtual size_t GetDepthStride()const = 0;
+ virtual const UploadBufferDesc& GetDesc()const = 0;
+ };
+
+ struct TextureUploaderDesc
+ {
+
+ };
+
+ class ITextureUploader : public IObject
+ {
+ public:
+ virtual void RenderThreadUpdate(IDeviceContext *pContext) = 0;
+ virtual void AllocateUploadBuffer(const UploadBufferDesc& Desc, bool IsRenderThread, IUploadBuffer **ppBuffer) = 0;
+ virtual void ScheduleGPUCopy(ITexture *pDstTexture, Uint32 ArraySlice, Uint32 MipLevel, IUploadBuffer *pUploadBuffer) = 0;
+ virtual void RecycleBuffer(IUploadBuffer *pUploadBuffer) = 0;
+ };
+
+ void CreateTextureUploader(IRenderDevice *pDevice, const TextureUploaderDesc& Desc, ITextureUploader **ppUploader);
+}
diff --git a/Graphics/GraphicsTools/include/TextureUploaderBase.h b/Graphics/GraphicsTools/include/TextureUploaderBase.h
new file mode 100644
index 00000000..0bd43bcd
--- /dev/null
+++ b/Graphics/GraphicsTools/include/TextureUploaderBase.h
@@ -0,0 +1,79 @@
+/* Copyright 2015-2017 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "TextureUploader.h"
+#include "ObjectBase.h"
+#include "HashUtils.h"
+#include "RefCntAutoPtr.h"
+
+namespace std
+{
+ template<>
+ struct hash<Diligent::UploadBufferDesc>
+ {
+ size_t operator()(const Diligent::UploadBufferDesc &Desc) const
+ {
+ return Diligent::ComputeHash(Desc.Width, Desc.Height, Desc.Depth, static_cast<Diligent::Int32>(Desc.Format));
+ }
+ };
+}
+
+namespace Diligent
+{
+ class UploadBufferBase : public ObjectBase<IUploadBuffer>
+ {
+ public:
+ UploadBufferBase(IReferenceCounters *pRefCounters, const UploadBufferDesc &Desc) :
+ ObjectBase<IUploadBuffer>(pRefCounters),
+ m_Desc(Desc)
+ {
+ }
+
+ virtual void WaitForCopyScheduled() = 0;
+ virtual void* GetDataPtr() override final { return m_pData; }
+ virtual size_t GetRowStride() const override final{ return m_RowStride; }
+ virtual size_t GetDepthStride()const override final{ return m_DepthStride; }
+ virtual const UploadBufferDesc& GetDesc()const override final{ return m_Desc; }
+
+ protected:
+ const UploadBufferDesc m_Desc;
+ void* m_pData = 0;
+ size_t m_RowStride = 0;
+ size_t m_DepthStride = 0;
+ };
+
+ class TextureUploaderBase : public ObjectBase<ITextureUploader>
+ {
+ public:
+ TextureUploaderBase(IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const TextureUploaderDesc Desc) :
+ ObjectBase<ITextureUploader>(pRefCounters),
+ m_pDevice(pDevice)
+ {}
+
+ protected:
+ RefCntAutoPtr<IRenderDevice> m_pDevice;
+ };
+
+}
diff --git a/Graphics/GraphicsTools/include/TextureUploaderD3D11.h b/Graphics/GraphicsTools/include/TextureUploaderD3D11.h
new file mode 100644
index 00000000..48d48aa3
--- /dev/null
+++ b/Graphics/GraphicsTools/include/TextureUploaderD3D11.h
@@ -0,0 +1,44 @@
+/* Copyright 2015-2017 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "TextureUploaderBase.h"
+namespace Diligent
+{
+ class TextureUploaderD3D11 : public TextureUploaderBase
+ {
+ public:
+ TextureUploaderD3D11(IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const TextureUploaderDesc Desc);
+ ~TextureUploaderD3D11();
+ virtual void RenderThreadUpdate(IDeviceContext *pContext)override final;
+
+ virtual void AllocateUploadBuffer(const UploadBufferDesc& Desc, bool IsRenderThread, IUploadBuffer **ppBuffer)override final;
+ virtual void ScheduleGPUCopy(ITexture *pDstTexture, Uint32 ArraySlice, Uint32 MipLevel, IUploadBuffer *pUploadBuffer)override final;
+ virtual void RecycleBuffer(IUploadBuffer *pUploadBuffer)override final;
+
+ private:
+ struct InternalData;
+ std::unique_ptr<InternalData> m_pInternalData;
+ };
+} \ No newline at end of file
diff --git a/Graphics/GraphicsTools/include/TextureUploaderD3D12.h b/Graphics/GraphicsTools/include/TextureUploaderD3D12.h
new file mode 100644
index 00000000..ff11ec9c
--- /dev/null
+++ b/Graphics/GraphicsTools/include/TextureUploaderD3D12.h
@@ -0,0 +1,45 @@
+/* Copyright 2015-2017 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "TextureUploaderBase.h"
+
+namespace Diligent
+{
+ class TextureUploaderD3D12 : public TextureUploaderBase
+ {
+ public:
+ TextureUploaderD3D12(IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const TextureUploaderDesc Desc);
+ ~TextureUploaderD3D12();
+ virtual void RenderThreadUpdate(IDeviceContext *pContext)override final;
+
+ virtual void AllocateUploadBuffer(const UploadBufferDesc& Desc, bool IsRenderThread, IUploadBuffer **ppBuffer)override final;
+ virtual void ScheduleGPUCopy(ITexture *pDstTexture, Uint32 ArraySlice, Uint32 MipLevel, IUploadBuffer *pUploadBuffer)override final;
+ virtual void RecycleBuffer(IUploadBuffer *pUploadBuffer)override final;
+
+ private:
+ struct InternalData;
+ std::unique_ptr<InternalData> m_pInternalData;
+ };
+}
diff --git a/Graphics/GraphicsTools/include/TextureUploaderGL.h b/Graphics/GraphicsTools/include/TextureUploaderGL.h
new file mode 100644
index 00000000..5e868870
--- /dev/null
+++ b/Graphics/GraphicsTools/include/TextureUploaderGL.h
@@ -0,0 +1,45 @@
+/* Copyright 2015-2017 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "TextureUploaderBase.h"
+
+namespace Diligent
+{
+ class TextureUploaderGL : public TextureUploaderBase
+ {
+ public:
+ TextureUploaderGL(IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const TextureUploaderDesc Desc);
+ ~TextureUploaderGL();
+ virtual void RenderThreadUpdate(IDeviceContext *pContext)override final;
+
+ virtual void AllocateUploadBuffer(const UploadBufferDesc& Desc, bool IsRenderThread, IUploadBuffer **ppBuffer)override final;
+ virtual void ScheduleGPUCopy(ITexture *pDstTexture, Uint32 ArraySlice, Uint32 MipLevel, IUploadBuffer *pUploadBuffer)override final;
+ virtual void RecycleBuffer(IUploadBuffer *pUploadBuffer)override final;
+
+ private:
+ struct InternalData;
+ std::unique_ptr<InternalData> m_pInternalData;
+ };
+}
diff --git a/Graphics/GraphicsTools/include/VariableSizeGPUAllocationsManager.h b/Graphics/GraphicsTools/include/VariableSizeGPUAllocationsManager.h
index b1cb9693..f299ca07 100644
--- a/Graphics/GraphicsTools/include/VariableSizeGPUAllocationsManager.h
+++ b/Graphics/GraphicsTools/include/VariableSizeGPUAllocationsManager.h
@@ -42,9 +42,9 @@ namespace Diligent
{
OffsetType Offset;
OffsetType Size;
- Uint64 CmdListNumber;
- StaleAllocationAttribs(OffsetType _Offset, OffsetType _Size, Uint64 _CmdListNumber) :
- Offset(_Offset), Size(_Size), CmdListNumber(_CmdListNumber)
+ Uint64 FenceValue;
+ StaleAllocationAttribs(OffsetType _Offset, OffsetType _Size, Uint64 _FenceValue) :
+ Offset(_Offset), Size(_Size), FenceValue(_FenceValue)
{}
};
@@ -73,22 +73,22 @@ namespace Diligent
VariableSizeGPUAllocationsManager(const VariableSizeGPUAllocationsManager&) = delete;
VariableSizeGPUAllocationsManager& operator = (const VariableSizeGPUAllocationsManager&) = delete;
- void Free(OffsetType Offset, OffsetType Size, Uint64 CmdListNumber)
+ void Free(OffsetType Offset, OffsetType Size, Uint64 FenceValue)
{
// Do not release the block immediately, but add
// it to the queue instead
- m_StaleAllocations.emplace_back(Offset, Size, CmdListNumber);
+ m_StaleAllocations.emplace_back(Offset, Size, FenceValue);
m_StaleAllocationsSize += Size;
}
// Releases stale allocation from completed command lists
- // The method takes the NUMBER of completed cmd lists (N)
- // and releases all allocations whose number n < N
- // (n == N is NOT released)
- void ReleaseStaleAllocations(Uint64 NumCompletedCmdLists)
+ // The method takes the last known completed fence value N
+ // and releases all allocations whose associated fence value
+ // is at most N (n <= N)
+ void ReleaseStaleAllocations(Uint64 LastCompletedFenceValue)
{
// Free all allocations from the beginning of the queue that belong to completed command lists
- while(!m_StaleAllocations.empty() && m_StaleAllocations.front().CmdListNumber < NumCompletedCmdLists)
+ while(!m_StaleAllocations.empty() && m_StaleAllocations.front().FenceValue <= LastCompletedFenceValue)
{
auto &OldestAllocation = m_StaleAllocations.front();
VariableSizeAllocationsManager::Free(OldestAllocation.Offset, OldestAllocation.Size);
diff --git a/Graphics/GraphicsTools/readme.md b/Graphics/GraphicsTools/readme.md
new file mode 100644
index 00000000..08d612d5
--- /dev/null
+++ b/Graphics/GraphicsTools/readme.md
@@ -0,0 +1,26 @@
+
+# GraphicsTools
+
+Implementation of common grpahics Utilities
+
+# Release Notes
+
+## 2.1
+
+### New features
+
+* Added [TextureUploader](include/TextureUploaderGL.h) interface and its implementations on
+ [D3D11](include/TextureUploaderD3D11.h), [D3D12](include/TextureUploaderD3D12.h), [OpenGL/GLES](include/TextureUploaderGL.h)
+
+## 2.0
+
+Reworked the API to follow D3D12 style
+
+## 1.0
+
+Initial release
+
+
+**Copyright 2015-2017 Egor Yusov**
+
+[Diligent Graphics](http://diligentgraphics.com) \ No newline at end of file
diff --git a/Graphics/GraphicsTools/src/BasicShaderSourceStreamFactory.cpp b/Graphics/GraphicsTools/src/BasicShaderSourceStreamFactory.cpp
index 6c1db669..b35d3427 100644
--- a/Graphics/GraphicsTools/src/BasicShaderSourceStreamFactory.cpp
+++ b/Graphics/GraphicsTools/src/BasicShaderSourceStreamFactory.cpp
@@ -63,7 +63,7 @@ namespace Diligent
String FullPath = SearchDir + ( (Name[0] == '\\' || Name[0] == '/') ? Name + 1 : Name);
if( !FileSystem::FileExists( FullPath.c_str() ) )
continue;
- pBasicFileStream = new BasicFileStream( FullPath.c_str(), EFileAccessMode::Read );
+ pBasicFileStream = MakeNewRCObj<BasicFileStream>()( FullPath.c_str(), EFileAccessMode::Read );
if( pBasicFileStream->IsValid() )
{
bFileCreated = true;
@@ -81,7 +81,7 @@ namespace Diligent
else
{
*ppStream = nullptr;
- LOG_ERROR_AND_THROW( "Failed to create input stream for source file ", Name )
+ LOG_ERROR( "Failed to create input stream for source file ", Name )
}
}
} \ No newline at end of file
diff --git a/Graphics/GraphicsTools/src/GraphicsUtilities.cpp b/Graphics/GraphicsTools/src/GraphicsUtilities.cpp
index e0ae1dce..9b5beb4f 100644
--- a/Graphics/GraphicsTools/src/GraphicsUtilities.cpp
+++ b/Graphics/GraphicsTools/src/GraphicsUtilities.cpp
@@ -25,6 +25,9 @@
#include "GraphicsUtilities.h"
#include "DebugUtilities.h"
#include <algorithm>
+#include <functional>
+
+#define PI_F 3.1415926f
namespace Diligent
{
@@ -61,9 +64,184 @@ const Char* GetValueTypeString( VALUE_TYPE Val )
}
}
+class TexFormatToViewFormatConverter
+{
+public:
+ TexFormatToViewFormatConverter()
+ {
+ static_assert(TEXTURE_VIEW_SHADER_RESOURCE == 1, "TEXTURE_VIEW_SHADER_RESOURCE == 1 expected");
+ static_assert(TEXTURE_VIEW_RENDER_TARGET == 2, "TEXTURE_VIEW_RENDER_TARGET == 2 expected");
+ static_assert(TEXTURE_VIEW_DEPTH_STENCIL == 3, "TEXTURE_VIEW_DEPTH_STENCIL == 3 expected");
+ static_assert(TEXTURE_VIEW_UNORDERED_ACCESS == 4, "TEXTURE_VIEW_UNORDERED_ACCESS == 4 expected");
+#define INIT_TEX_VIEW_FORMAT_INFO(TexFmt, SRVFmt, RTVFmt, DSVFmt, UAVFmt)\
+ {\
+ m_ViewFormats[ TexFmt ][TEXTURE_VIEW_SHADER_RESOURCE-1] = TEX_FORMAT_##SRVFmt; \
+ m_ViewFormats[ TexFmt ][TEXTURE_VIEW_RENDER_TARGET-1] = TEX_FORMAT_##RTVFmt; \
+ m_ViewFormats[ TexFmt ][TEXTURE_VIEW_DEPTH_STENCIL-1] = TEX_FORMAT_##DSVFmt; \
+ m_ViewFormats[ TexFmt ][TEXTURE_VIEW_UNORDERED_ACCESS-1] = TEX_FORMAT_##UAVFmt; \
+ }
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA32_TYPELESS, RGBA32_FLOAT, RGBA32_FLOAT, UNKNOWN, RGBA32_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA32_FLOAT, RGBA32_FLOAT, RGBA32_FLOAT, UNKNOWN, RGBA32_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA32_UINT, RGBA32_UINT, RGBA32_UINT, UNKNOWN, RGBA32_UINT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA32_SINT, RGBA32_SINT, RGBA32_SINT, UNKNOWN, RGBA32_SINT);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGB32_TYPELESS, RGB32_FLOAT, RGB32_FLOAT, UNKNOWN, RGB32_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGB32_FLOAT, RGB32_FLOAT, RGB32_FLOAT, UNKNOWN, RGB32_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGB32_UINT, RGB32_UINT, RGB32_UINT, UNKNOWN, RGB32_UINT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGB32_SINT, RGB32_SINT, RGB32_SINT, UNKNOWN, RGB32_SINT);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA16_TYPELESS, RGBA16_FLOAT, RGBA16_FLOAT, UNKNOWN, RGBA16_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA16_FLOAT, RGBA16_FLOAT, RGBA16_FLOAT, UNKNOWN, RGBA16_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA16_UNORM, RGBA16_UNORM, RGBA16_UNORM, UNKNOWN, RGBA16_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA16_UINT, RGBA16_UINT, RGBA16_UINT, UNKNOWN, RGBA16_UINT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA16_SNORM, RGBA16_SNORM, RGBA16_SNORM, UNKNOWN, RGBA16_SNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA16_SINT, RGBA16_SINT, RGBA16_SINT, UNKNOWN, RGBA16_SINT);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG32_TYPELESS, RG32_FLOAT, RG32_FLOAT, UNKNOWN, RG32_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG32_FLOAT, RG32_FLOAT, RG32_FLOAT, UNKNOWN, RG32_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG32_UINT, RG32_UINT, RG32_UINT, UNKNOWN, RG32_UINT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG32_SINT, RG32_SINT, RG32_SINT, UNKNOWN, RG32_SINT);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R32G8X24_TYPELESS, R32_FLOAT_X8X24_TYPELESS, UNKNOWN, D32_FLOAT_S8X24_UINT, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_D32_FLOAT_S8X24_UINT, R32_FLOAT_X8X24_TYPELESS, UNKNOWN, D32_FLOAT_S8X24_UINT, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS,R32_FLOAT_X8X24_TYPELESS, UNKNOWN, D32_FLOAT_S8X24_UINT, R32_FLOAT_X8X24_TYPELESS);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_X32_TYPELESS_G8X24_UINT, X32_TYPELESS_G8X24_UINT, UNKNOWN, D32_FLOAT_S8X24_UINT, X32_TYPELESS_G8X24_UINT);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGB10A2_TYPELESS, RGB10A2_UNORM, RGB10A2_UNORM, UNKNOWN, RGB10A2_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGB10A2_UNORM, RGB10A2_UNORM, RGB10A2_UNORM, UNKNOWN, RGB10A2_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGB10A2_UINT, RGB10A2_UINT, RGB10A2_UINT, UNKNOWN, RGB10A2_UINT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R11G11B10_FLOAT, R11G11B10_FLOAT, R11G11B10_FLOAT, UNKNOWN, R11G11B10_FLOAT);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA8_TYPELESS, RGBA8_UNORM_SRGB, RGBA8_UNORM_SRGB, UNKNOWN, RGBA8_UNORM_SRGB);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA8_UNORM, RGBA8_UNORM, RGBA8_UNORM, UNKNOWN, RGBA8_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA8_UNORM_SRGB, RGBA8_UNORM_SRGB, RGBA8_UNORM_SRGB, UNKNOWN, RGBA8_UNORM_SRGB);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA8_UINT, RGBA8_UINT, RGBA8_UINT, UNKNOWN, RGBA8_UINT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA8_SNORM, RGBA8_SNORM, RGBA8_SNORM, UNKNOWN, RGBA8_SNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGBA8_SINT, RGBA8_SINT, RGBA8_SINT, UNKNOWN, RGBA8_SINT);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG16_TYPELESS, RG16_FLOAT, RG16_FLOAT, UNKNOWN, RG16_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG16_FLOAT, RG16_FLOAT, RG16_FLOAT, UNKNOWN, RG16_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG16_UNORM, RG16_UNORM, RG16_UNORM, UNKNOWN, RG16_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG16_UINT, RG16_UINT, RG16_UINT, UNKNOWN, RG16_UINT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG16_SNORM, RG16_SNORM, RG16_SNORM, UNKNOWN, RG16_SNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG16_SINT, RG16_SINT, RG16_SINT, UNKNOWN, RG16_SINT);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R32_TYPELESS, R32_FLOAT, R32_FLOAT, D32_FLOAT, R32_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_D32_FLOAT, R32_FLOAT, R32_FLOAT, D32_FLOAT, R32_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R32_FLOAT, R32_FLOAT, R32_FLOAT, D32_FLOAT, R32_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R32_UINT, R32_UINT, R32_UINT, UNKNOWN, R32_UINT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R32_SINT, R32_SINT, R32_SINT, UNKNOWN, R32_SINT);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R24G8_TYPELESS, R24_UNORM_X8_TYPELESS, UNKNOWN, D24_UNORM_S8_UINT, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_D24_UNORM_S8_UINT, R24_UNORM_X8_TYPELESS, UNKNOWN, D24_UNORM_S8_UINT, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R24_UNORM_X8_TYPELESS, R24_UNORM_X8_TYPELESS, UNKNOWN, D24_UNORM_S8_UINT, R24_UNORM_X8_TYPELESS);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_X24_TYPELESS_G8_UINT, X24_TYPELESS_G8_UINT, UNKNOWN, D24_UNORM_S8_UINT, X24_TYPELESS_G8_UINT);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG8_TYPELESS, RG8_UNORM, RG8_UNORM, UNKNOWN, RG8_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG8_UNORM, RG8_UNORM, RG8_UNORM, UNKNOWN, RG8_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG8_UINT, RG8_UINT, RG8_UINT, UNKNOWN, RG8_UINT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG8_SNORM, RG8_SNORM, RG8_SNORM, UNKNOWN, RG8_SNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG8_SINT, RG8_SINT, RG8_SINT, UNKNOWN, RG8_SINT);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R16_TYPELESS, R16_FLOAT, R16_FLOAT, UNKNOWN, R16_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R16_FLOAT, R16_FLOAT, R16_FLOAT, UNKNOWN, R16_FLOAT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_D16_UNORM, R16_UNORM, R16_UNORM, D16_UNORM, R16_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R16_UNORM, R16_UNORM, R16_UNORM, D16_UNORM, R16_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R16_UINT, R16_UINT, R16_UINT, UNKNOWN, R16_UINT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R16_SNORM, R16_SNORM, R16_SNORM, UNKNOWN, R16_SNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R16_SINT, R16_SINT, R16_SINT, UNKNOWN, R16_SINT);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R8_TYPELESS, R8_UNORM, R8_UNORM, UNKNOWN, R8_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R8_UNORM, R8_UNORM, R8_UNORM, UNKNOWN, R8_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R8_UINT, R8_UINT, R8_UINT, UNKNOWN, R8_UINT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R8_SNORM, R8_SNORM, R8_SNORM, UNKNOWN, R8_SNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R8_SINT, R8_SINT, R8_SINT, UNKNOWN, R8_SINT);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_A8_UNORM, A8_UNORM, A8_UNORM, UNKNOWN, A8_UNORM);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R1_UNORM, R1_UNORM, R1_UNORM, UNKNOWN, R1_UNORM);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RGB9E5_SHAREDEXP, RGB9E5_SHAREDEXP, RGB9E5_SHAREDEXP, UNKNOWN, RGB9E5_SHAREDEXP);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_RG8_B8G8_UNORM, RG8_B8G8_UNORM, RG8_B8G8_UNORM, UNKNOWN, RG8_B8G8_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_G8R8_G8B8_UNORM, G8R8_G8B8_UNORM, G8R8_G8B8_UNORM, UNKNOWN, G8R8_G8B8_UNORM);
+
+ // http://www.g-truc.net/post-0335.html
+ // http://renderingpipeline.com/2012/07/texture-compression/
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC1_TYPELESS, BC1_UNORM_SRGB, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC1_UNORM, BC1_UNORM, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC1_UNORM_SRGB, BC1_UNORM_SRGB, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC2_TYPELESS, BC2_UNORM_SRGB, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC2_UNORM, BC2_UNORM, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC2_UNORM_SRGB, BC2_UNORM_SRGB, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC3_TYPELESS, BC3_UNORM_SRGB, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC3_UNORM, BC3_UNORM, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC3_UNORM_SRGB, BC3_UNORM_SRGB, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC4_TYPELESS, BC4_UNORM, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC4_UNORM, BC4_UNORM, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC4_SNORM, BC4_SNORM, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC5_TYPELESS, BC5_UNORM, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC5_UNORM, BC5_UNORM, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC5_SNORM, BC5_SNORM, UNKNOWN, UNKNOWN, UNKNOWN);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_B5G6R5_UNORM, B5G6R5_UNORM, B5G6R5_UNORM, UNKNOWN, B5G6R5_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_B5G5R5A1_UNORM, B5G5R5A1_UNORM, B5G5R5A1_UNORM, UNKNOWN, B5G5R5A1_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BGRA8_UNORM, BGRA8_UNORM, BGRA8_UNORM, UNKNOWN, BGRA8_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BGRX8_UNORM, BGRX8_UNORM, BGRX8_UNORM, UNKNOWN, BGRX8_UNORM);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, R10G10B10_XR_BIAS_A2_UNORM, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BGRA8_TYPELESS, BGRA8_UNORM_SRGB, BGRA8_UNORM_SRGB, UNKNOWN, BGRA8_UNORM_SRGB);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BGRA8_UNORM_SRGB, BGRA8_UNORM_SRGB, BGRA8_UNORM_SRGB, UNKNOWN, BGRA8_UNORM_SRGB);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BGRX8_TYPELESS, BGRX8_UNORM_SRGB, BGRX8_UNORM_SRGB, UNKNOWN, BGRX8_UNORM_SRGB);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BGRX8_UNORM_SRGB, BGRX8_UNORM_SRGB, BGRX8_UNORM_SRGB, UNKNOWN, BGRX8_UNORM_SRGB);
+
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC6H_TYPELESS, BC6H_UF16, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC6H_UF16, BC6H_UF16, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC6H_SF16, BC6H_SF16, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC7_TYPELESS, BC7_UNORM_SRGB, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC7_UNORM, BC7_UNORM, UNKNOWN, UNKNOWN, UNKNOWN);
+ INIT_TEX_VIEW_FORMAT_INFO( TEX_FORMAT_BC7_UNORM_SRGB, BC7_UNORM_SRGB, UNKNOWN, UNKNOWN, UNKNOWN);
+#undef INIT_TVIEW_FORMAT_INFO
+ }
+
+ TEXTURE_FORMAT GetViewFormat(TEXTURE_FORMAT Format, TEXTURE_VIEW_TYPE ViewType, Uint32 BindFlags)
+ {
+ VERIFY(ViewType > TEXTURE_VIEW_UNDEFINED && ViewType < TEXTURE_VIEW_NUM_VIEWS, "Unexpected texture view type");
+ VERIFY(Format >= TEX_FORMAT_UNKNOWN && Format < TEX_FORMAT_NUM_FORMATS, "Unknown texture format");
+ switch (Format)
+ {
+ case TEX_FORMAT_R16_TYPELESS:
+ {
+ if (BindFlags & BIND_DEPTH_STENCIL)
+ {
+ static TEXTURE_FORMAT D16_ViewFmts[] =
+ {
+ TEX_FORMAT_R16_UNORM, TEX_FORMAT_R16_UNORM, TEX_FORMAT_D16_UNORM, TEX_FORMAT_R16_UNORM
+ };
+ return D16_ViewFmts[ViewType - 1];
+ }
+ }
+
+ default: /*do nothing*/break;
+ }
+
+ return m_ViewFormats[Format][ViewType-1];
+ }
+
+private:
+
+ TEXTURE_FORMAT m_ViewFormats[TEX_FORMAT_NUM_FORMATS][TEXTURE_VIEW_NUM_VIEWS-1];
+};
+
+TEXTURE_FORMAT GetDefaultTextureViewFormat(TEXTURE_FORMAT TextureFormat, TEXTURE_VIEW_TYPE ViewType, Uint32 BindFlags)
+{
+ static TexFormatToViewFormatConverter FmtConverter;
+ return FmtConverter.GetViewFormat(TextureFormat, ViewType, BindFlags);
+}
+
const TextureFormatAttribs& GetTextureFormatAttribs( TEXTURE_FORMAT Format )
{
- static TextureFormatAttribs FmtAttribs[TEX_FORMAT_NUM_FORMATS] = {};
+ static TextureFormatAttribs FmtAttribs[TEX_FORMAT_NUM_FORMATS];
static bool bIsInit = false;
// Note that this implementation is thread-safe
// Even if two threads try to call the function at the same time,
@@ -516,7 +694,7 @@ static const Char* GetBufferModeString( BUFFER_MODE Mode )
{
#define INIT_BUFF_MODE_STR(Mode)BufferModeStrings[Mode] = #Mode
INIT_BUFF_MODE_STR( BUFFER_MODE_UNDEFINED );
- INIT_BUFF_MODE_STR( BUFFER_MODE_FORMATED );
+ INIT_BUFF_MODE_STR( BUFFER_MODE_FORMATTED );
INIT_BUFF_MODE_STR( BUFFER_MODE_STRUCTURED );
#undef INIT_BUFF_MODE_STR
static_assert(BUFFER_MODE_NUM_MODES == BUFFER_MODE_STRUCTURED + 1, "Not all buffer mode strings initialized.");
@@ -556,7 +734,7 @@ String GetBufferDescString( const BufferDesc &Desc )
Str += "; Mode: ";
Str += GetBufferModeString(Desc.Mode);
- if( Desc.Mode == BUFFER_MODE_FORMATED )
+ if( Desc.Mode == BUFFER_MODE_FORMATTED )
{
Str += "; Format: ";
Str += GetValueTypeString( Desc.Format.ValueType );
@@ -601,9 +779,10 @@ Uint32 ComputeMipLevelsCount( Uint32 Width, Uint32 Height, Uint32 Depth )
return ComputeMipLevelsCount( std::max(std::max( Width, Height ), Depth) );
}
-void CreateUniformBuffer( IRenderDevice *pDevice, Uint32 Size, IBuffer **ppBuffer, USAGE Usage, Uint32 BindFlag, Uint32 CPUAccessFlags)
+void CreateUniformBuffer( IRenderDevice *pDevice, Uint32 Size, const Char *Name, IBuffer **ppBuffer, USAGE Usage, Uint32 BindFlag, Uint32 CPUAccessFlags)
{
BufferDesc CBDesc;
+ CBDesc.Name = Name;
CBDesc.uiSizeInBytes = Size;
CBDesc.Usage = Usage;
CBDesc.BindFlags = BindFlag;
@@ -611,4 +790,75 @@ void CreateUniformBuffer( IRenderDevice *pDevice, Uint32 Size, IBuffer **ppBuffe
pDevice->CreateBuffer( CBDesc, BufferData(), ppBuffer );
}
+template<class TConverter>
+void GenerateCheckerBoardPatternInternal(Uint32 Width, Uint32 Height, TEXTURE_FORMAT Fmt, Uint32 HorzCells, Uint32 VertCells, Uint8 *pData, Uint32 StrideInBytes, TConverter Converter)
+{
+ const auto& FmtAttribs = GetTextureFormatAttribs(Fmt);
+ for (Uint32 y = 0; y < Height; ++y)
+ {
+ for (Uint32 x = 0; x < Width; ++x)
+ {
+ float horzWave = sin((static_cast<float>(x) + 0.5f) / static_cast<float>(Width) * PI_F * static_cast<float>(HorzCells));
+ float vertWave = sin((static_cast<float>(y) + 0.5f) / static_cast<float>(Height) * PI_F * static_cast<float>(VertCells));
+ float val = horzWave * vertWave;
+ val = std::max( std::min( val*20.f, +1.f), -1.f );
+ val = val * 0.5f + 1.f;
+ val = val * 0.5f + 0.25f;
+ Uint8 *pDstTexel = pData + x * FmtAttribs.NumComponents * FmtAttribs.ComponentSize + y * StrideInBytes;
+ Converter(pDstTexel, FmtAttribs.NumComponents, val);
+ }
+ }
+}
+
+static float LinearToSRGB(float x)
+{
+ // This is exactly the sRGB curve
+ //return x < 0.0031308 ? 12.92 * x : 1.055 * pow(abs(x), 1.0 / 2.4) - 0.055;
+
+ // This is cheaper but nearly equivalent
+ return x < 0.0031308f ? 12.92f * x : 1.13005f * sqrtf(abs(x - 0.00228f)) - 0.13448f * x + 0.005719f;
+}
+
+
+void GenerateCheckerBoardPattern(Uint32 Width, Uint32 Height, TEXTURE_FORMAT Fmt, Uint32 HorzCells, Uint32 VertCells, Uint8 *pData, Uint32 StrideInBytes)
+{
+ const auto& FmtAttribs = GetTextureFormatAttribs(Fmt);
+ switch (FmtAttribs.ComponentType)
+ {
+ case COMPONENT_TYPE_UINT:
+ case COMPONENT_TYPE_UNORM:
+ GenerateCheckerBoardPatternInternal(Width, Height, Fmt, HorzCells, VertCells, pData, StrideInBytes,
+ [](Uint8 *pDstTexel, Uint32 NumComponents, float fVal)
+ {
+ Uint8 uVal = static_cast<Uint8>(fVal * 255.f);
+ for (Uint32 c = 0; c < NumComponents; ++c)
+ pDstTexel[c] = uVal;
+ });
+ break;
+
+ case COMPONENT_TYPE_UNORM_SRGB:
+ GenerateCheckerBoardPatternInternal(Width, Height, Fmt, HorzCells, VertCells, pData, StrideInBytes,
+ [](Uint8 *pDstTexel, Uint32 NumComponents, float fVal)
+ {
+ Uint8 uVal = static_cast<Uint8>( LinearToSRGB(fVal) * 255.f);
+ for (Uint32 c = 0; c < NumComponents; ++c)
+ pDstTexel[c] = uVal;
+ });
+ break;
+
+ case COMPONENT_TYPE_FLOAT:
+ GenerateCheckerBoardPatternInternal(Width, Height, Fmt, HorzCells, VertCells, pData, StrideInBytes,
+ [](Uint8 *pDstTexel, Uint32 NumComponents, float fVal)
+ {
+ for (Uint32 c = 0; c < NumComponents; ++c)
+ (reinterpret_cast<float*>(pDstTexel))[c] = fVal;
+ });
+ break;
+
+ default:
+ UNSUPPORTED("Unsupported component type")
+ return;
+ }
+}
+
}
diff --git a/Graphics/GraphicsTools/src/TextureUploader.cpp b/Graphics/GraphicsTools/src/TextureUploader.cpp
new file mode 100644
index 00000000..f056f162
--- /dev/null
+++ b/Graphics/GraphicsTools/src/TextureUploader.cpp
@@ -0,0 +1,52 @@
+/* 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 "TextureUploaderD3D11.h"
+#include "TextureUploaderD3D12.h"
+#include "TextureUploaderGL.h"
+
+namespace Diligent
+{
+ void CreateTextureUploader(IRenderDevice *pDevice, const TextureUploaderDesc& Desc, ITextureUploader **ppUploader)
+ {
+ *ppUploader = nullptr;
+ switch (pDevice->GetDeviceCaps().DevType)
+ {
+ case DeviceType::D3D11:
+ *ppUploader = MakeNewRCObj<TextureUploaderD3D11>()( pDevice, Desc );
+ break;
+
+ case DeviceType::D3D12:
+ *ppUploader = MakeNewRCObj<TextureUploaderD3D12>()( pDevice, Desc );
+ break;
+
+ case DeviceType::OpenGLES:
+ case DeviceType::OpenGL:
+ *ppUploader = MakeNewRCObj<TextureUploaderGL>()( pDevice, Desc );
+ break;
+ }
+ if (*ppUploader != nullptr)
+ (*ppUploader)->AddRef();
+ }
+}
diff --git a/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp b/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp
new file mode 100644
index 00000000..3677f7eb
--- /dev/null
+++ b/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp
@@ -0,0 +1,326 @@
+/* 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 <unordered_map>
+#include <deque>
+#include <mutex>
+#include <atlbase.h>
+#include <d3d11.h>
+
+#include "TextureUploaderD3D11.h"
+#include "RenderDeviceD3D11.h"
+#include "DeviceContextD3D11.h"
+#include "TextureD3D11.h"
+#include "DXGITypeConversions.h"
+
+namespace Diligent
+{
+ class UploadBufferD3D11 : public UploadBufferBase
+ {
+ public:
+ UploadBufferD3D11(Diligent::IReferenceCounters *pRefCounters, const UploadBufferDesc &Desc, ID3D11Texture2D *pStagingTexture) :
+ UploadBufferBase(pRefCounters, Desc),
+ m_pStagingTexture(pStagingTexture)
+ {}
+
+ ~UploadBufferD3D11()
+ {
+ if(m_pStagingTexture)
+ LOG_INFO_MESSAGE("UploadBufferD3D11: releasing ", m_Desc.Width, 'x', m_Desc.Height, " Fmt=", m_Desc.Format, " staging texture")
+ }
+
+ void SetDataPtr(void *pData, size_t RowStride, size_t DepthStride)
+ {
+ m_pData = pData;
+ m_RowStride = RowStride;
+ m_DepthStride = DepthStride;
+ }
+
+ // http://en.cppreference.com/w/cpp/thread/condition_variable
+ void WaitForMap()
+ {
+ m_BufferMappedSignal.Wait();
+ }
+
+ void SignalMapped()
+ {
+ m_BufferMappedSignal.Trigger();
+ }
+
+ void SignalCopyScheduled()
+ {
+ m_CopyScheduledSignal.Trigger();
+ }
+
+ virtual void WaitForCopyScheduled()override final
+ {
+ m_CopyScheduledSignal.Wait();
+ }
+
+ bool DbgIsCopyScheduled()
+ {
+ return m_CopyScheduledSignal.IsTriggered();
+ }
+
+ bool DbgIsMapped()
+ {
+ return m_BufferMappedSignal.IsTriggered();
+ }
+
+ void Reset()
+ {
+ m_pData = nullptr;
+ m_RowStride = 0;
+ m_DepthStride = 0;
+ m_BufferMappedSignal.Reset();
+ m_CopyScheduledSignal.Reset();
+ }
+
+ ID3D11Texture2D* GetStagingTex() { return m_pStagingTexture; }
+ private:
+ ThreadingTools::Signal m_BufferMappedSignal;
+ ThreadingTools::Signal m_CopyScheduledSignal;
+ CComPtr<ID3D11Texture2D> m_pStagingTexture;
+ };
+
+ struct TextureUploaderD3D11::InternalData
+ {
+ struct PendingBufferOperation
+ {
+ enum Operation
+ {
+ Map,
+ Copy,
+ MapAndCache
+ }operation;
+ RefCntAutoPtr<UploadBufferD3D11> pUploadBuffer;
+ CComPtr<ID3D11Resource> pd3d11NativeDstTexture;
+ UINT DstSubresource = 0;
+
+ PendingBufferOperation(Operation op, UploadBufferD3D11* pBuff) :
+ operation(op),
+ pUploadBuffer(pBuff)
+ {}
+ PendingBufferOperation(Operation op, UploadBufferD3D11* pBuff, ID3D11Resource *pd3d11DstTex, UINT dstSubres) :
+ operation(op),
+ pUploadBuffer(pBuff),
+ pd3d11NativeDstTexture(pd3d11DstTex),
+ DstSubresource(dstSubres)
+ {}
+ };
+
+ InternalData(IRenderDevice *pDevice)
+ {
+ RefCntAutoPtr<IRenderDeviceD3D11> pDeviceD3D11(pDevice, IID_RenderDeviceD3D11);
+ m_pd3d11NativeDevice = pDeviceD3D11->GetD3D11Device();
+ }
+
+ CComPtr<ID3D11Device> m_pd3d11NativeDevice;
+
+ void SwapMapQueues()
+ {
+ std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx);
+ m_PendingOperations.swap(m_InWorkOperations);
+ }
+
+ void EnqueCopy(UploadBufferD3D11 *pUploadBuffer, ID3D11Resource *pd3d11DstTex, UINT dstSubres)
+ {
+ std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx);
+ m_PendingOperations.emplace_back(PendingBufferOperation::Operation::Copy, pUploadBuffer, pd3d11DstTex, dstSubres);
+ }
+
+ void EnqueMap(UploadBufferD3D11 *pUploadBuffer, PendingBufferOperation::Operation Op)
+ {
+ std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx);
+ m_PendingOperations.emplace_back(Op, pUploadBuffer);
+ }
+
+ std::mutex m_PendingOperationsMtx;
+ std::vector< PendingBufferOperation > m_PendingOperations;
+ std::vector< PendingBufferOperation > m_InWorkOperations;
+
+ std::mutex m_UploadBuffCacheMtx;
+ std::unordered_map< UploadBufferDesc, std::deque< RefCntAutoPtr<UploadBufferD3D11> > > m_UploadBufferCache;
+ };
+
+ TextureUploaderD3D11::TextureUploaderD3D11(IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const TextureUploaderDesc Desc) :
+ TextureUploaderBase(pRefCounters, pDevice, Desc),
+ m_pInternalData(new InternalData(pDevice))
+ {
+ }
+
+ TextureUploaderD3D11::~TextureUploaderD3D11()
+ {
+ for (auto BuffQueueIt : m_pInternalData->m_UploadBufferCache)
+ {
+ if (BuffQueueIt.second.size())
+ {
+ const auto &desc = BuffQueueIt.first;
+ auto &FmtInfo = m_pDevice->GetTextureFormatInfo(desc.Format);
+ LOG_INFO_MESSAGE("TextureUploaderD3D11: releasing ", BuffQueueIt.second.size(), ' ', desc.Width, 'x', desc.Height, 'x', desc.Depth, ' ', FmtInfo.Name, " staging texture(s) ")
+ }
+ }
+ }
+
+ void TextureUploaderD3D11::RenderThreadUpdate(Diligent::IDeviceContext *pContext)
+ {
+ m_pInternalData->SwapMapQueues();
+ if (!m_pInternalData->m_InWorkOperations.empty())
+ {
+ RefCntAutoPtr<IDeviceContextD3D11> pContextD3D11(pContext, IID_DeviceContextD3D11);
+ auto* pd3d11NativeCtx = pContextD3D11->GetD3D11DeviceContext();
+
+ for (auto &OperationInfo : m_pInternalData->m_InWorkOperations)
+ {
+ auto &pBuffer = OperationInfo.pUploadBuffer;
+
+ switch (OperationInfo.operation)
+ {
+ case InternalData::PendingBufferOperation::MapAndCache:
+ case InternalData::PendingBufferOperation::Map:
+ {
+ D3D11_MAPPED_SUBRESOURCE MappedData;
+ auto hr = pd3d11NativeCtx->Map(pBuffer->GetStagingTex(), 0, D3D11_MAP_WRITE, D3D11_MAP_FLAG_DO_NOT_WAIT, &MappedData);
+ if (SUCCEEDED(hr))
+ {
+ pBuffer->SetDataPtr(MappedData.pData, MappedData.RowPitch, MappedData.DepthPitch);
+ pBuffer->SignalMapped();
+ if (OperationInfo.operation == InternalData::PendingBufferOperation::MapAndCache)
+ {
+ std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx);
+ auto &Cache = m_pInternalData->m_UploadBufferCache;
+ Cache[pBuffer->GetDesc()].emplace_back( std::move(pBuffer) );
+ }
+ }
+ else
+ {
+ if (hr == DXGI_ERROR_WAS_STILL_DRAWING)
+ {
+ m_pInternalData->EnqueMap(pBuffer, OperationInfo.operation);
+ }
+ else
+ {
+ LOG_ERROR("Unknown DX error when mapping staging texture: ", hr)
+ }
+ }
+ }
+ break;
+
+ case InternalData::PendingBufferOperation::Copy:
+ {
+ VERIFY(pBuffer->DbgIsMapped(), "Upload buffer must be copied only after it has been mapped");
+ pd3d11NativeCtx->Unmap(pBuffer->GetStagingTex(), 0);
+ pd3d11NativeCtx->CopySubresourceRegion(OperationInfo.pd3d11NativeDstTexture, OperationInfo.DstSubresource,
+ 0, 0, 0, // DstX, DstY, DstZ
+ pBuffer->GetStagingTex(),
+ 0, // SrcSubresource
+ nullptr // pSrcBox
+ );
+ pBuffer->SignalCopyScheduled();
+ }
+ break;
+ }
+ }
+ m_pInternalData->m_InWorkOperations.clear();
+ }
+ }
+
+ void TextureUploaderD3D11::AllocateUploadBuffer(const UploadBufferDesc& Desc, bool IsRenderThread, IUploadBuffer **ppBuffer)
+ {
+ *ppBuffer = nullptr;
+
+ {
+ std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx);
+ auto &Cache = m_pInternalData->m_UploadBufferCache;
+ if (!Cache.empty())
+ {
+ auto DequeIt = Cache.find(Desc);
+ if (DequeIt != Cache.end())
+ {
+ auto &Deque = DequeIt->second;
+ if (!Deque.empty())
+ {
+ *ppBuffer = Deque.front().Detach();
+ Deque.pop_front();
+ }
+ }
+ }
+ }
+
+ if( *ppBuffer == nullptr )
+ {
+ D3D11_TEXTURE2D_DESC StagingTexDesc =
+ {
+ static_cast<UINT>(Desc.Width),
+ static_cast<UINT>(Desc.Height),
+ 1, // UINT MipLevels;
+ 1, // UINT ArraySize;
+ TexFormatToDXGI_Format(Desc.Format),
+ {1, 0}, // DXGI_SAMPLE_DESC SampleDesc;
+ D3D11_USAGE_STAGING,
+ 0, // UINT BindFlags;
+ D3D11_CPU_ACCESS_WRITE, // UINT CPUAccessFlags;
+ 0, // UINT MiscFlags;
+ };
+
+ CComPtr<ID3D11Texture2D> pStagingTex;
+ HRESULT hr = m_pInternalData->m_pd3d11NativeDevice->CreateTexture2D(&StagingTexDesc, nullptr, &pStagingTex);
+ if (FAILED(hr))
+ {
+ LOG_ERROR_MESSAGE("Failed to allocate staging D3D11 texture")
+ return;
+ }
+
+ LOG_INFO_MESSAGE("TextureUploaderD3D11: created ", Desc.Width, 'x', Desc.Height, ' ', m_pDevice->GetTextureFormatInfo(Desc.Format).Name, " staging texture")
+
+ RefCntAutoPtr<UploadBufferD3D11> pUploadBuffer(MakeNewRCObj<UploadBufferD3D11>()(Desc, pStagingTex));
+ m_pInternalData->EnqueMap(pUploadBuffer, InternalData::PendingBufferOperation::Map);
+ pUploadBuffer->WaitForMap();
+ *ppBuffer = pUploadBuffer.Detach();
+ }
+ }
+
+ void TextureUploaderD3D11::ScheduleGPUCopy(Diligent::ITexture *pDstTexture,
+ Uint32 ArraySlice,
+ Uint32 MipLevel,
+ IUploadBuffer *pUploadBuffer)
+ {
+ auto *pUploadBufferD3D11 = ValidatedCast<UploadBufferD3D11>(pUploadBuffer);
+ RefCntAutoPtr<ITextureD3D11> pDstTexD3D11(pDstTexture, IID_TextureD3D11);
+ auto *pd3d11NativeDstTex = pDstTexD3D11->GetD3D11Texture();
+ const auto &DstTexDesc = pDstTexture->GetDesc();
+ UINT DstSubres = D3D11CalcSubresource(static_cast<UINT>(MipLevel), static_cast<UINT>(ArraySlice), static_cast<UINT>(DstTexDesc.MipLevels));
+ m_pInternalData->EnqueCopy(pUploadBufferD3D11, pd3d11NativeDstTex, DstSubres);
+ }
+
+ void TextureUploaderD3D11::RecycleBuffer(IUploadBuffer *pUploadBuffer)
+ {
+ auto *pUploadBufferD3D11 = ValidatedCast<UploadBufferD3D11>(pUploadBuffer);
+ VERIFY(pUploadBufferD3D11->DbgIsCopyScheduled(), "Upload buffer must be recycled only after copy operation has been scheduled on the GPU");
+ pUploadBufferD3D11->Reset();
+
+ m_pInternalData->EnqueMap(pUploadBufferD3D11, InternalData::PendingBufferOperation::MapAndCache);
+ }
+} \ No newline at end of file
diff --git a/Graphics/GraphicsTools/src/TextureUploaderD3D12.cpp b/Graphics/GraphicsTools/src/TextureUploaderD3D12.cpp
new file mode 100644
index 00000000..2791d914
--- /dev/null
+++ b/Graphics/GraphicsTools/src/TextureUploaderD3D12.cpp
@@ -0,0 +1,274 @@
+/* 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 <atlbase.h>
+#include <mutex>
+#include <unordered_map>
+#include <deque>
+#include <d3d12.h>
+
+#include "TextureUploaderD3D12.h"
+#include "RenderDeviceD3D12.h"
+#include "BufferD3D12.h"
+#include "TextureD3D12.h"
+
+namespace Diligent
+{
+
+ class UploadBufferD3D12 : public UploadBufferBase
+ {
+ public:
+ UploadBufferD3D12(IReferenceCounters *pRefCounters,
+ IRenderDeviceD3D12 *pRenderDeviceD3D12,
+ const UploadBufferDesc &Desc,
+ IBuffer *pStagingBuffer,
+ void *pData,
+ size_t RowStride,
+ size_t DepthStride) :
+ UploadBufferBase(pRefCounters, Desc),
+ m_pDeviceD3D12(pRenderDeviceD3D12),
+ m_pStagingBuffer(pStagingBuffer)
+ {
+ m_pData = pData;
+ m_RowStride = RowStride;
+ m_DepthStride = DepthStride;
+ }
+
+ ~UploadBufferD3D12()
+ {
+ m_pStagingBuffer->Unmap(nullptr, MAP_WRITE, 0);
+ LOG_INFO_MESSAGE("Releasing staging buffer of size ", m_pStagingBuffer->GetDesc().uiSizeInBytes )
+ }
+
+ void SignalCopyScheduled()
+ {
+ m_CopyScheduledSignal.Trigger();
+ }
+
+ void Reset()
+ {
+ m_CopyScheduledSignal.Reset();
+ }
+
+ virtual void WaitForCopyScheduled()override final
+ {
+ m_CopyScheduledSignal.Wait();
+ }
+
+ IBuffer* GetStagingBuffer() { return m_pStagingBuffer; }
+
+ bool DbgIsCopyScheduled()const { return m_CopyScheduledSignal.IsTriggered(); }
+ private:
+
+ ThreadingTools::Signal m_CopyScheduledSignal;
+
+ RefCntAutoPtr<IBuffer> m_pStagingBuffer;
+ RefCntAutoPtr<IRenderDeviceD3D12> m_pDeviceD3D12;
+ };
+
+ struct TextureUploaderD3D12::InternalData
+ {
+ InternalData(IRenderDevice *pDevice) :
+ m_pDeviceD3D12(pDevice, IID_RenderDeviceD3D12)
+ {
+ m_pd3d12NativeDevice = m_pDeviceD3D12->GetD3D12Device();
+ }
+
+ CComPtr<ID3D12Device> m_pd3d12NativeDevice;
+ RefCntAutoPtr<IRenderDeviceD3D12> m_pDeviceD3D12;
+
+ void SwapMapQueues()
+ {
+ std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx);
+ m_PendingOperations.swap(m_InWorkOperations);
+ }
+
+ void EnqueCopy(UploadBufferD3D12 *pUploadBuffer, ITextureD3D12 *pDstTex, Uint32 dstSlice, Uint32 dstMip)
+ {
+ std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx);
+ m_PendingOperations.emplace_back(PendingBufferOperation::Operation::Copy, pUploadBuffer, pDstTex, dstSlice, dstMip);
+ }
+
+ std::mutex m_PendingOperationsMtx;
+ struct PendingBufferOperation
+ {
+ enum Operation
+ {
+ Copy
+ }operation;
+ RefCntAutoPtr<UploadBufferD3D12> pUploadBuffer;
+ RefCntAutoPtr<ITextureD3D12> pDstTexture;
+ Uint32 DstSlice = 0;
+ Uint32 DstMip = 0;
+
+ PendingBufferOperation(Operation op, UploadBufferD3D12* pBuff) :
+ operation(op),
+ pUploadBuffer(pBuff)
+ {}
+ PendingBufferOperation(Operation op, UploadBufferD3D12* pBuff, ITextureD3D12 *pDstTex, Uint32 dstSlice, Uint32 dstMip) :
+ operation(op),
+ pUploadBuffer(pBuff),
+ pDstTexture(pDstTex),
+ DstSlice(dstSlice),
+ DstMip(dstMip)
+ {}
+ };
+ std::vector< PendingBufferOperation > m_PendingOperations;
+ std::vector< PendingBufferOperation > m_InWorkOperations;
+
+ std::mutex m_UploadBuffCacheMtx;
+ std::unordered_map< UploadBufferDesc, std::deque< std::pair<Uint64, RefCntAutoPtr<UploadBufferD3D12> > > > m_UploadBufferCache;
+ };
+
+ TextureUploaderD3D12::TextureUploaderD3D12(IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const TextureUploaderDesc Desc) :
+ TextureUploaderBase(pRefCounters, pDevice, Desc),
+ m_pInternalData(new InternalData(pDevice))
+ {
+ }
+
+ TextureUploaderD3D12::~TextureUploaderD3D12()
+ {
+ for (auto BuffQueueIt : m_pInternalData->m_UploadBufferCache)
+ {
+ if (BuffQueueIt.second.size())
+ {
+ const auto &desc = BuffQueueIt.first;
+ auto &FmtInfo = m_pDevice->GetTextureFormatInfo(desc.Format);
+ LOG_INFO_MESSAGE("TextureUploaderD3D12: releasing ", BuffQueueIt.second.size(), ' ', desc.Width, 'x', desc.Height, 'x', desc.Depth, ' ', FmtInfo.Name, " upload buffer(s) ")
+ }
+ }
+ }
+
+ void TextureUploaderD3D12::RenderThreadUpdate(IDeviceContext *pContext)
+ {
+ m_pInternalData->SwapMapQueues();
+ if (!m_pInternalData->m_InWorkOperations.empty())
+ {
+ for (auto &OperationInfo : m_pInternalData->m_InWorkOperations)
+ {
+ auto &pBuffer = OperationInfo.pUploadBuffer;
+
+ switch (OperationInfo.operation)
+ {
+ case InternalData::PendingBufferOperation::Copy:
+ {
+ TextureSubResData SubResData(pBuffer->GetStagingBuffer(), static_cast<Uint32>(pBuffer->GetRowStride()));
+ const auto &TexDesc = OperationInfo.pDstTexture->GetDesc();
+ Box DstBox;
+ DstBox.MaxX = TexDesc.Width;
+ DstBox.MaxY = TexDesc.Height;
+ OperationInfo.pDstTexture->UpdateData(pContext, OperationInfo.DstMip, OperationInfo.DstSlice, DstBox, SubResData);
+ pBuffer->SignalCopyScheduled();
+ }
+ break;
+ }
+ }
+
+ m_pInternalData->m_InWorkOperations.clear();
+ }
+ }
+
+ void TextureUploaderD3D12::AllocateUploadBuffer(const UploadBufferDesc& Desc, bool IsRenderThread, IUploadBuffer **ppBuffer)
+ {
+ *ppBuffer = nullptr;
+
+ {
+ std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx);
+ auto &Cache = m_pInternalData->m_UploadBufferCache;
+ if (!Cache.empty())
+ {
+ auto DequeIt = Cache.find(Desc);
+ if (DequeIt != Cache.end())
+ {
+ auto &Deque = DequeIt->second;
+ if (!Deque.empty())
+ {
+ auto &FrontBuff = Deque.front();
+ if (m_pInternalData->m_pDeviceD3D12->IsFenceSignaled(FrontBuff.first))
+ {
+ *ppBuffer = FrontBuff.second.Detach();
+ Deque.pop_front();
+ }
+ }
+ }
+ }
+ }
+
+ // No available buffer found in the cache
+ if(*ppBuffer == nullptr)
+ {
+ BufferDesc BuffDesc;
+ BuffDesc.Name = "Staging buffer for UploadBufferD3D12";
+ BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ BuffDesc.Usage = USAGE_CPU_ACCESSIBLE;
+
+ const auto &TexFmtInfo = m_pDevice->GetTextureFormatInfo(Desc.Format);
+ Uint32 RowStride = Desc.Width * TexFmtInfo.ComponentSize * TexFmtInfo.NumComponents;
+ static_assert((D3D12_TEXTURE_DATA_PITCH_ALIGNMENT & (D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1)) == 0, "Alginment is expected to be power of 2");
+ Uint32 AlignmentMask = D3D12_TEXTURE_DATA_PITCH_ALIGNMENT-1;
+ RowStride = (RowStride + AlignmentMask) & (~AlignmentMask);
+
+ BuffDesc.uiSizeInBytes = Desc.Height * RowStride;
+ RefCntAutoPtr<IBuffer> pStagingBuffer;
+ m_pDevice->CreateBuffer(BuffDesc, BufferData(), &pStagingBuffer);
+
+ PVoid CpuVirtualAddress = nullptr;
+ pStagingBuffer->Map(nullptr, MAP_WRITE, 0, CpuVirtualAddress);
+ if (CpuVirtualAddress == nullptr)
+ {
+ LOG_ERROR_MESSAGE("Failed to map upload buffer")
+ return;
+ }
+
+ LOG_INFO_MESSAGE("Created staging buffer of size ", BuffDesc.uiSizeInBytes )
+
+ RefCntAutoPtr<UploadBufferD3D12> pUploadBuffer(MakeNewRCObj<UploadBufferD3D12>()(m_pInternalData->m_pDeviceD3D12, Desc, pStagingBuffer, CpuVirtualAddress, RowStride, 0));
+ *ppBuffer = pUploadBuffer.Detach();
+ }
+ }
+
+ void TextureUploaderD3D12::ScheduleGPUCopy(ITexture *pDstTexture,
+ Uint32 ArraySlice,
+ Uint32 MipLevel,
+ IUploadBuffer *pUploadBuffer)
+ {
+ auto *pUploadBufferD3D12 = ValidatedCast<UploadBufferD3D12>(pUploadBuffer);
+ RefCntAutoPtr<ITextureD3D12> pDstTexD3D12(pDstTexture, IID_TextureD3D12);
+ m_pInternalData->EnqueCopy(pUploadBufferD3D12, pDstTexD3D12, ArraySlice, MipLevel);
+ }
+
+ void TextureUploaderD3D12::RecycleBuffer(IUploadBuffer *pUploadBuffer)
+ {
+ auto *pUploadBufferD3D12 = ValidatedCast<UploadBufferD3D12>(pUploadBuffer);
+ VERIFY(pUploadBufferD3D12->DbgIsCopyScheduled(), "Upload buffer must be recycled only after copy operation has been scheduled on the GPU");
+ pUploadBufferD3D12->Reset();
+
+ std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx);
+ auto &Cache = m_pInternalData->m_UploadBufferCache;
+ auto &Deque = Cache[pUploadBufferD3D12->GetDesc()];
+ Uint64 FenceValue = m_pInternalData->m_pDeviceD3D12->GetNextFenceValue();
+ Deque.emplace_back( FenceValue, pUploadBufferD3D12 );
+ }
+}
diff --git a/Graphics/GraphicsTools/src/TextureUploaderGL.cpp b/Graphics/GraphicsTools/src/TextureUploaderGL.cpp
new file mode 100644
index 00000000..2eee70f4
--- /dev/null
+++ b/Graphics/GraphicsTools/src/TextureUploaderGL.cpp
@@ -0,0 +1,271 @@
+/* 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 <mutex>
+#include <deque>
+#include <unordered_map>
+#include "TextureUploaderGL.h"
+
+namespace Diligent
+{
+
+ class UploadBufferGL : public UploadBufferBase
+ {
+ public:
+ UploadBufferGL(IReferenceCounters *pRefCounters, const UploadBufferDesc &Desc) :
+ UploadBufferBase(pRefCounters, Desc)
+ {}
+
+ void SetDataPtr(void *pData, size_t RowStride, size_t DepthStride)
+ {
+ m_pData = pData;
+ m_RowStride = RowStride;
+ m_DepthStride = DepthStride;
+ }
+
+ // http://en.cppreference.com/w/cpp/thread/condition_variable
+ void WaitForMap()
+ {
+ m_BufferMappedSignal.Wait();
+ }
+
+ void SignalMapped()
+ {
+ m_BufferMappedSignal.Trigger();
+ }
+
+ void SignalCopyScheduled()
+ {
+ m_CopyScheduledSignal.Trigger();
+ }
+
+ virtual void WaitForCopyScheduled()override final
+ {
+ m_CopyScheduledSignal.Wait();
+ }
+
+ bool DbgIsCopyScheduled()const { return m_CopyScheduledSignal.IsTriggered(); }
+
+ void Reset()
+ {
+ m_BufferMappedSignal.Reset();
+ m_CopyScheduledSignal.Reset();
+ m_pData = nullptr;
+ // Do not zero out strides
+ }
+
+ private:
+ friend class TextureUploaderGL;
+ ThreadingTools::Signal m_BufferMappedSignal;
+ ThreadingTools::Signal m_CopyScheduledSignal;
+ RefCntAutoPtr<IBuffer> m_pStagingBuffer;
+ };
+
+ struct TextureUploaderGL::InternalData
+ {
+ void SwapMapQueues()
+ {
+ std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx);
+ m_PendingOperations.swap(m_InWorkOperations);
+ }
+
+ void EnqueCopy(UploadBufferGL *pUploadBuffer, ITexture *pDstTexture, Uint32 dstSlice, Uint32 dstMip)
+ {
+ std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx);
+ m_PendingOperations.emplace_back(PendingBufferOperation::Operation::Copy, pUploadBuffer, pDstTexture, dstSlice, dstMip);
+ }
+
+ void EnqueMap(UploadBufferGL *pUploadBuffer)
+ {
+ std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx);
+ m_PendingOperations.emplace_back(PendingBufferOperation::Operation::Map, pUploadBuffer);
+ }
+
+
+ struct PendingBufferOperation
+ {
+ enum Operation
+ {
+ Map,
+ Copy
+ }operation;
+ RefCntAutoPtr<UploadBufferGL> pUploadBuffer;
+ RefCntAutoPtr<ITexture> pDstTexture;
+ Uint32 DstSlice = 0;
+ Uint32 DstMip = 0;
+
+ PendingBufferOperation(Operation op, UploadBufferGL* pBuff) :
+ operation(op),
+ pUploadBuffer(pBuff)
+ {}
+ PendingBufferOperation(Operation op, UploadBufferGL* pBuff, ITexture *pDstTex, Uint32 dstSlice, Uint32 dstMip) :
+ operation(op),
+ pUploadBuffer(pBuff),
+ pDstTexture(pDstTex),
+ DstSlice(dstSlice),
+ DstMip(dstMip)
+ {}
+ };
+
+ std::mutex m_PendingOperationsMtx;
+ std::vector< PendingBufferOperation > m_PendingOperations;
+ std::vector< PendingBufferOperation > m_InWorkOperations;
+
+ std::mutex m_UploadBuffCacheMtx;
+ std::unordered_map< UploadBufferDesc, std::deque<RefCntAutoPtr<UploadBufferGL> > > m_UploadBufferCache;
+ };
+
+ TextureUploaderGL::TextureUploaderGL(IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const TextureUploaderDesc Desc) :
+ TextureUploaderBase(pRefCounters, pDevice, Desc),
+ m_pInternalData(new InternalData())
+ {
+ }
+
+ TextureUploaderGL::~TextureUploaderGL()
+ {
+ for (auto BuffQueueIt : m_pInternalData->m_UploadBufferCache)
+ {
+ if (BuffQueueIt.second.size())
+ {
+ const auto &desc = BuffQueueIt.first;
+ auto &FmtInfo = m_pDevice->GetTextureFormatInfo(desc.Format);
+ LOG_INFO_MESSAGE("TextureUploaderGL: releasing ", BuffQueueIt.second.size(), ' ', desc.Width, 'x', desc.Height, 'x', desc.Depth, ' ', FmtInfo.Name, " upload buffer(s) ")
+ }
+ }
+ }
+
+ void TextureUploaderGL::RenderThreadUpdate(IDeviceContext *pContext)
+ {
+ m_pInternalData->SwapMapQueues();
+ if (!m_pInternalData->m_InWorkOperations.empty())
+ {
+ for (auto &OperationInfo : m_pInternalData->m_InWorkOperations)
+ {
+ auto &pBuffer = OperationInfo.pUploadBuffer;
+
+ switch (OperationInfo.operation)
+ {
+ case InternalData::PendingBufferOperation::Map:
+ {
+ Uint32 RowStride = static_cast<Uint32>(pBuffer->GetRowStride());
+ if (pBuffer->m_pStagingBuffer == nullptr)
+ {
+ const auto &Desc = pBuffer->GetDesc();
+ BufferDesc BuffDesc;
+ BuffDesc.Name = "Staging buffer for UploadBufferGL";
+ BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ BuffDesc.Usage = USAGE_CPU_ACCESSIBLE;
+
+ const auto &TexFmtInfo = m_pDevice->GetTextureFormatInfo(Desc.Format);
+ RowStride = Desc.Width * TexFmtInfo.ComponentSize * TexFmtInfo.NumComponents;
+ const Uint32 Alignment = 16;
+ const Uint32 AlignmentMask = Alignment-1;
+ RowStride = (RowStride + AlignmentMask) & (~AlignmentMask);
+
+ BuffDesc.uiSizeInBytes = Desc.Height * RowStride;
+ RefCntAutoPtr<IBuffer> pStagingBuffer;
+ m_pDevice->CreateBuffer(BuffDesc, BufferData(), &pBuffer->m_pStagingBuffer);
+ }
+
+ PVoid CpuAddress = nullptr;
+ pBuffer->m_pStagingBuffer->Map(pContext, MAP_WRITE, MAP_FLAG_DISCARD, CpuAddress);
+ pBuffer->SetDataPtr(CpuAddress, RowStride, 0);
+
+ pBuffer->SignalMapped();
+ }
+ break;
+
+ case InternalData::PendingBufferOperation::Copy:
+ {
+ pBuffer->m_pStagingBuffer->Unmap(pContext, MAP_WRITE, MAP_FLAG_DISCARD);
+ TextureSubResData SubResData(pBuffer->m_pStagingBuffer, static_cast<Uint32>(pBuffer->GetRowStride()));
+ Box DstBox;
+ const auto &TexDesc = OperationInfo.pDstTexture->GetDesc();
+ DstBox.MaxX = TexDesc.Width;
+ DstBox.MaxY = TexDesc.Height;
+ OperationInfo.pDstTexture->UpdateData(pContext, OperationInfo.DstMip, OperationInfo.DstSlice, DstBox, SubResData);
+ pBuffer->SignalCopyScheduled();
+ }
+ break;
+ }
+ }
+ m_pInternalData->m_InWorkOperations.clear();
+ }
+ }
+
+ void TextureUploaderGL::AllocateUploadBuffer(const UploadBufferDesc& Desc, bool IsRenderThread, IUploadBuffer **ppBuffer)
+ {
+ *ppBuffer = nullptr;
+ RefCntAutoPtr<UploadBufferGL> pUploadBuffer;
+
+ {
+ std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx);
+ auto &Cache = m_pInternalData->m_UploadBufferCache;
+ if (!Cache.empty())
+ {
+ auto DequeIt = Cache.find(Desc);
+ if (DequeIt != Cache.end())
+ {
+ auto &Deque = DequeIt->second;
+ if (!Deque.empty())
+ {
+ pUploadBuffer.Attach(Deque.front().Detach());
+ Deque.pop_front();
+ }
+ }
+ }
+ }
+
+ if( !pUploadBuffer )
+ {
+ pUploadBuffer = MakeNewRCObj<UploadBufferGL>()(Desc);
+ LOG_INFO_MESSAGE("TextureUploaderGL: created upload buffer for ", Desc.Width, 'x', Desc.Height, 'x', Desc.Depth, ' ', m_pDevice->GetTextureFormatInfo(Desc.Format).Name, " texture" )
+ }
+
+ m_pInternalData->EnqueMap(pUploadBuffer);
+ pUploadBuffer->WaitForMap();
+ *ppBuffer = pUploadBuffer.Detach();
+ }
+
+ void TextureUploaderGL::ScheduleGPUCopy(ITexture *pDstTexture,
+ Uint32 ArraySlice,
+ Uint32 MipLevel,
+ IUploadBuffer *pUploadBuffer)
+ {
+ auto *pUploadBufferGL = ValidatedCast<UploadBufferGL>(pUploadBuffer);
+ m_pInternalData->EnqueCopy(pUploadBufferGL, pDstTexture, ArraySlice, MipLevel);
+ }
+
+ void TextureUploaderGL::RecycleBuffer(IUploadBuffer *pUploadBuffer)
+ {
+ auto *pUploadBufferGL = ValidatedCast<UploadBufferGL>(pUploadBuffer);
+ VERIFY(pUploadBufferGL->DbgIsCopyScheduled(), "Upload buffer must be recycled only after copy operation has been scheduled on the GPU");
+ pUploadBufferGL->Reset();
+
+ std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx);
+ auto &Cache = m_pInternalData->m_UploadBufferCache;
+ auto &Deque = Cache[pUploadBufferGL->GetDesc()];
+ Deque.emplace_back( pUploadBufferGL );
+ }
+}