git.s-ol.nu ~forks/DiligentCore / 9220e5a
Merged master assiduous 6 months ago
75 changed file(s) with 1040 addition(s) and 474 deletion(s). Raw diff Collapse all Expand all
0 ThirdParty
2525 env:
2626 - CONFIG=Debug
2727 - os: osx
28 osx_image: xcode11.1
28 osx_image: xcode12.2
2929 compiler: clang
3030 env:
3131 - CONFIG=Debug
3232 - IOS=false
3333 - os: osx
34 osx_image: xcode11.1
34 osx_image: xcode12.2
3535 compiler: clang
3636 env:
3737 - CONFIG=Debug
4141 env:
4242 - CONFIG=Release
4343 - os: osx
44 osx_image: xcode11.1
44 osx_image: xcode12.2
4545 compiler: clang
4646 env:
4747 - CONFIG=Release
4848 - IOS=false
4949 - os: osx
50 osx_image: xcode11.1
50 osx_image: xcode12.2
5151 compiler: clang
5252 env:
5353 - CONFIG=Release
2323 errcho "WARNING: could not load the provided clang-format for validation."
2424 errcho " clang-format exists in the system path however its version is $SYS_BIN_VERSION instead of $BIN_VERSION"
2525 errcho " Should the validation fail, you can try skipping it by setting the cmake option:"
26 errcho " DILIGENT_SKIP_FORMAT_VALIDATION"
26 errcho " DILIGENT_NO_FORMAT_VALIDATION"
2727 fi
2828 BIN="$SYS_BIN"
2929 fi
0 set CMAKE_URL="https://github.com/Kitware/CMake/releases/download/v3.18.2/cmake-3.18.2-win64-x64.zip"
0 set CMAKE_URL="https://github.com/Kitware/CMake/releases/download/v3.19.3/cmake-3.19.3-win64-x64.zip"
11 appveyor DownloadFile %CMAKE_URL% -FileName cmake.zip
22 7z x cmake.zip -oC:\projects\deps > nul
33 move C:\projects\deps\cmake-* C:\projects\deps\cmake
0 CMAKE_VERSION="3.18.2"
1 VULKAN_SDK_VER="1.2.154.0"
0 CMAKE_VERSION="3.19.3"
1 VULKAN_SDK_VER="1.2.162.1"
22
33 if [ "$TRAVIS_OS_NAME" = "osx" ]; then
4 wget --no-check-certificate https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz &&
5 tar -xzf cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz
6 export PATH=$PWD/cmake-${CMAKE_VERSION}-Darwin-x86_64/CMake.app/Contents/bin:$PATH
4 wget --no-check-certificate https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-macos-universal.tar.gz &&
5 tar -xzf cmake-${CMAKE_VERSION}-macos-universal.tar.gz
6 export PATH=$PWD/cmake-${CMAKE_VERSION}-macos-universal/CMake.app/Contents/bin:$PATH
77 cmake --version
88 # Download Vulkan SDK
99 export VK_SDK_DMG=vulkansdk-macos-$VULKAN_SDK_VER.dmg
99
1010 if [ "$TRAVIS_OS_NAME" = "osx" ]; then
1111 if [ "$IOS" = "true" ]; then
12 cmake .. -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DVULKAN_SDK="$VULKAN_SDK" $1 -G "Xcode" || return
12 cmake .. -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DVULKAN_SDK="$VULKAN_SDK" $1 -G "Xcode" -T buildsystem=1 || return
1313 XCODE_BUILD_SETTINGS="CODE_SIGN_IDENTITY= CODE_SIGNING_REQUIRED=NO"
1414 else
15 cmake .. $1 -G "Xcode" || return
15 cmake .. $1 -G "Xcode" -T buildsystem=1 || return
1616 XCODE_BUILD_SETTINGS=""
1717 fi
1818 xcodebuild -configuration ${CONFIG} ${XCODE_BUILD_SETTINGS} | xcpretty && return ${PIPESTATUS[0]}
99
1010 if [ "$TRAVIS_OS_NAME" = "osx" ]; then
1111 if [ "$IOS" = "true" ]; then
12 cmake .. $1 -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DVULKAN_SDK="$VULKAN_SDK" -DCMAKE_INSTALL_PREFIX=install -G "Xcode" || return
12 cmake .. $1 -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DVULKAN_SDK="$VULKAN_SDK" -DCMAKE_INSTALL_PREFIX=install -G "Xcode" -T buildsystem=1 || return
1313 XCODE_BUILD_SETTINGS="CODE_SIGN_IDENTITY= CODE_SIGNING_REQUIRED=NO"
1414 else
15 cmake .. $1 -DCMAKE_INSTALL_PREFIX=install -G "Xcode" || return
15 cmake .. $1 -DCMAKE_INSTALL_PREFIX=install -G "Xcode" -T buildsystem=1 || return
1616 XCODE_BUILD_SETTINGS=""
1717 fi
1818 xcodebuild -target install -configuration ${CONFIG} ${XCODE_BUILD_SETTINGS} | xcpretty && return ${PIPESTATUS[0]}
4040 public:
4141 Signal()
4242 {
43 m_SignaledValue = 0;
44 m_NumThreadsAwaken = 0;
43 m_SignaledValue.store(0);
44 m_NumThreadsAwaken.store(0);
4545 }
4646
4747 // http://en.cppreference.com/w/cpp/thread/condition_variable
5757 // std::condition_variable works only with std::unique_lock<std::mutex>
5858 std::lock_guard<std::mutex> Lock{m_Mutex};
5959 VERIFY(SignalValue != 0, "Signal value must not be 0");
60 VERIFY(m_SignaledValue == 0 && m_NumThreadsAwaken == 0, "Not all threads have been awaken since the signal was triggered last time, or the signal has not been reset");
61 m_SignaledValue = SignalValue;
60 VERIFY(m_SignaledValue.load() == 0 && m_NumThreadsAwaken.load() == 0, "Not all threads have been awaken since the signal was triggered last time, or the signal has not been reset");
61 m_SignaledValue.store(SignalValue);
6262 }
6363 // Unlocking is done before notifying, to avoid waking up the waiting
6464 // thread only to block again (see notify_one for details)
8686 std::unique_lock<std::mutex> Lock(m_Mutex);
8787 // It is safe to check m_SignaledValue since we are holding
8888 // the mutex
89 if (m_SignaledValue == 0)
89 if (m_SignaledValue.load() == 0)
9090 {
91 m_CondVar.wait(Lock, [&] { return m_SignaledValue != 0; });
91 m_CondVar.wait(Lock, [&] { return m_SignaledValue.load() != 0; });
9292 }
93 int SignaledValue = m_SignaledValue;
94 // Count the number of threads awaken while holding the mutex
95 ++m_NumThreadsAwaken;
93 auto SignaledValue = m_SignaledValue.load();
94 // Update the number of threads awaken while holding the mutex
95 const auto NumThreadsAwaken = m_NumThreadsAwaken.fetch_add(1) + 1;
96 // fetch_add returns the original value immediately preceding the addition.
9697 if (AutoReset)
9798 {
9899 VERIFY(NumThreadsWaiting > 0, "Number of waiting threads must not be 0 when auto resetting the signal");
99100 // Reset the signal while holding the mutex. If Trigger() is executed by another
100101 // thread, it will wait until we release the mutex
101 if (m_NumThreadsAwaken == NumThreadsWaiting)
102 if (NumThreadsAwaken == NumThreadsWaiting)
102103 {
103 m_SignaledValue = 0;
104 m_NumThreadsAwaken = 0;
104 m_SignaledValue.store(0);
105 m_NumThreadsAwaken.store(0);
105106 }
106107 }
107108 return SignaledValue;
110111 void Reset()
111112 {
112113 std::lock_guard<std::mutex> Lock{m_Mutex};
113 m_SignaledValue = 0;
114 m_NumThreadsAwaken = 0;
114 m_SignaledValue.store(0);
115 m_NumThreadsAwaken.store(0);
115116 }
116117
117 bool IsTriggered() const { return m_SignaledValue != 0; }
118 bool IsTriggered() const { return m_SignaledValue.load() != 0; }
118119
119120 private:
120121 std::mutex m_Mutex;
121122 std::condition_variable m_CondVar;
122 std::atomic_int m_SignaledValue;
123 std::atomic_int m_NumThreadsAwaken;
123 std::atomic_int m_SignaledValue{0};
124 std::atomic_int m_NumThreadsAwaken{0};
124125
125126 Signal(const Signal&) = delete;
126127 Signal& operator=(const Signal&) = delete;
6565 static constexpr int DeletedObjectsToPurge = 32;
6666
6767 StateObjectsRegistry(IMemoryAllocator& RawAllocator, const Char* RegistryName) :
68 m_NumDeletedObjects{0},
6869 m_DescToObjHashMap(STD_ALLOCATOR_RAW_MEM(HashMapElem, RawAllocator, "Allocator for unordered_map<ResourceDescType, RefCntWeakPtr<IDeviceObject> >")),
6970 m_RegistryName{RegistryName}
7071 {}
2929 /// \file
3030 /// Diligent API information
3131
32 #define DILIGENT_API_VERSION 240081
32 #define DILIGENT_API_VERSION 240082
3333
3434 #include "../../../Primitives/interface/BasicTypes.h"
3535
18351835 ICommandList** ppCommandList) PURE;
18361836
18371837
1838 /// Executes recorded commands in a command list.
1839
1840 /// \param [in] pCommandList - Pointer to the command list to executre.
1841 /// \remarks After command list is executed, it is no longer valid and should be released.
1842 VIRTUAL void METHOD(ExecuteCommandList)(THIS_
1843 ICommandList* pCommandList) PURE;
1838 /// Submits an array of recorded command lists for execution.
1839
1840 /// \param [in] NumCommandLists - The number of command lists to execute.
1841 /// \param [in] ppCommandLists - Pointer to the array of NumCommandLists command lists to execute.
1842 /// \remarks After a command list is executed, it is no longer valid and must be released.
1843 VIRTUAL void METHOD(ExecuteCommandLists)(THIS_
1844 Uint32 NumCommandLists,
1845 ICommandList* const* ppCommandLists) PURE;
18441846
18451847
18461848 /// Tells the GPU to set a fence to a specified value after all previous work has completed.
22302232 # define IDeviceContext_ClearDepthStencil(This, ...) CALL_IFACE_METHOD(DeviceContext, ClearDepthStencil, This, __VA_ARGS__)
22312233 # define IDeviceContext_ClearRenderTarget(This, ...) CALL_IFACE_METHOD(DeviceContext, ClearRenderTarget, This, __VA_ARGS__)
22322234 # define IDeviceContext_FinishCommandList(This, ...) CALL_IFACE_METHOD(DeviceContext, FinishCommandList, This, __VA_ARGS__)
2233 # define IDeviceContext_ExecuteCommandList(This, ...) CALL_IFACE_METHOD(DeviceContext, ExecuteCommandList, This, __VA_ARGS__)
2235 # define IDeviceContext_ExecuteCommandLists(This, ...) CALL_IFACE_METHOD(DeviceContext, ExecuteCommandLists, This, __VA_ARGS__)
22342236 # define IDeviceContext_SignalFence(This, ...) CALL_IFACE_METHOD(DeviceContext, SignalFence, This, __VA_ARGS__)
22352237 # define IDeviceContext_WaitForFence(This, ...) CALL_IFACE_METHOD(DeviceContext, WaitForFence, This, __VA_ARGS__)
22362238 # define IDeviceContext_WaitForIdle(This, ...) CALL_IFACE_METHOD(DeviceContext, WaitForIdle, This, __VA_ARGS__)
15201520 /// Describes the device features
15211521 struct DeviceFeatures
15221522 {
1523 /// Indicates if device supports separable programs
1523 /// Indicates if device supports separable shader programs.
1524
1525 /// \remarks The only case when separable programs are not supported is when the engine is
1526 /// initialized in GLES3.0 mode. In GLES3.1+ and in all other backends, the
1527 /// feature is always enabled.
1528 /// In OpenGL backend, it may forcibly be disabled using ForceNonSeparablePrograms
1529 /// member of EngineGLCreateInfo struct (this is primarily used for testing).
1530 /// The are two main limitations when separable programs are disabled:
1531 /// - If the same shader variable is present in multiple shader stages,
1532 /// it will always be shared between all stages and different resources
1533 /// can't be bound to different stages.
1534 /// - Shader resource queries will be also disabled.
15241535 DEVICE_FEATURE_STATE SeparablePrograms DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
15251536
15261537 /// Indicates if device supports resource queries from shader objects.
228228 /// Implementation of IDeviceContext::FinishCommandList() in Direct3D11 backend.
229229 void DILIGENT_CALL_TYPE FinishCommandList(class ICommandList** ppCommandList) override final;
230230
231 /// Implementation of IDeviceContext::ExecuteCommandList() in Direct3D11 backend.
232 virtual void DILIGENT_CALL_TYPE ExecuteCommandList(class ICommandList* pCommandList) override final;
231 /// Implementation of IDeviceContext::ExecuteCommandLists() in Direct3D11 backend.
232 virtual void DILIGENT_CALL_TYPE ExecuteCommandLists(Uint32 NumCommandLists,
233 ICommandList* const* ppCommandLists) override final;
233234
234235 /// Implementation of IDeviceContext::SignalFence() in Direct3D11 backend.
235236 virtual void DILIGENT_CALL_TYPE SignalFence(IFence* pFence, Uint64 Value) override final;
19241924 #endif
19251925 }
19261926
1927 void DeviceContextD3D11Impl::ExecuteCommandList(ICommandList* pCommandList)
1927 void DeviceContextD3D11Impl::ExecuteCommandLists(Uint32 NumCommandLists,
1928 ICommandList* const* ppCommandLists)
19281929 {
19291930 if (m_bIsDeferred)
19301931 {
19321933 return;
19331934 }
19341935
1935 CommandListD3D11Impl* pCmdListD3D11 = ValidatedCast<CommandListD3D11Impl>(pCommandList);
1936 auto* pd3d11CmdList = pCmdListD3D11->GetD3D11CommandList();
1937 m_pd3d11DeviceContext->ExecuteCommandList(pd3d11CmdList,
1938 FALSE // A Boolean flag that determines whether the target context state is
1939 // saved prior to and restored after the execution of a command list.
1940 // * TRUE indicates that the runtime needs to save and restore the state.
1941 // * FALSE indicate that no state shall be saved or restored, which causes the
1942 // target context to return to its default state after the command list executes as if
1943 // ID3D11DeviceContext::ClearState() was called.
1944 );
1936 if (NumCommandLists == 0)
1937 return;
1938 DEV_CHECK_ERR(ppCommandLists != nullptr, "ppCommandLists must not be null when NumCommandLists is not zero");
1939
1940 for (Uint32 i = 0; i < NumCommandLists; ++i)
1941 {
1942 auto* pCmdListD3D11 = ValidatedCast<CommandListD3D11Impl>(ppCommandLists[i]);
1943 auto* pd3d11CmdList = pCmdListD3D11->GetD3D11CommandList();
1944 m_pd3d11DeviceContext->ExecuteCommandList(pd3d11CmdList,
1945 FALSE // A Boolean flag that determines whether the target context state is
1946 // saved prior to and restored after the execution of a command list.
1947 // * TRUE indicates that the runtime needs to save and restore the state.
1948 // * FALSE indicate that no state shall be saved or restored, which causes the
1949 // target context to return to its default state after the command list executes as if
1950 // ID3D11DeviceContext::ClearState() was called.
1951 );
1952 }
19451953
19461954 // Device context is now in default state
19471955 InvalidateState();
5151 virtual Uint64 DILIGENT_CALL_TYPE GetNextFenceValue() const override final { return m_NextFenceValue; }
5252
5353 // Implementation of ICommandQueueD3D12::Submit().
54 virtual Uint64 DILIGENT_CALL_TYPE Submit(ID3D12GraphicsCommandList* commandList) override final;
54 virtual Uint64 DILIGENT_CALL_TYPE Submit(Uint32 NumCommandLists,
55 ID3D12CommandList* const* ppCommandLists) override final;
5556
5657 // Implementation of ICommandQueueD3D12::GetD3D12CommandQueue().
5758 virtual ID3D12CommandQueue* DILIGENT_CALL_TYPE GetD3D12CommandQueue() override final { return m_pd3d12CmdQueue; }
233233 /// Implementation of IDeviceContext::FinishCommandList() in Direct3D12 backend.
234234 virtual void DILIGENT_CALL_TYPE FinishCommandList(class ICommandList** ppCommandList) override final;
235235
236 /// Implementation of IDeviceContext::ExecuteCommandList() in Direct3D12 backend.
237 virtual void DILIGENT_CALL_TYPE ExecuteCommandList(class ICommandList* pCommandList) override final;
236 /// Implementation of IDeviceContext::ExecuteCommandLists() in Direct3D12 backend.
237 virtual void DILIGENT_CALL_TYPE ExecuteCommandLists(Uint32 NumCommandLists,
238 ICommandList* const* ppCommandLists) override final;
238239
239240 /// Implementation of IDeviceContext::SignalFence() in Direct3D12 backend.
240241 virtual void DILIGENT_CALL_TYPE SignalFence(IFence* pFence, Uint64 Value) override final;
344345 void CommitScissorRects(class GraphicsContext& GraphCtx, bool ScissorEnable);
345346 void TransitionSubpassAttachments(Uint32 NextSubpass);
346347 void CommitSubpassRenderTargets();
347 void Flush(bool RequestNewCmdCtx);
348 void Flush(bool RequestNewCmdCtx,
349 Uint32 NumCommandLists = 0,
350 ICommandList* const* ppCommandLists = nullptr);
348351
349352 __forceinline void RequestCommandContext(RenderDeviceD3D12Impl* pDeviceD3D12Impl);
350353
173173
174174 void CloseAndExecuteTransientCommandContext(Uint32 CommandQueueIndex, PooledCommandContext&& Ctx);
175175
176 Uint64 CloseAndExecuteCommandContext(Uint32 QueueIndex,
177 PooledCommandContext&& Ctx,
178 bool DiscardStaleObjects,
179 std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>* pSignalFences);
176 Uint64 CloseAndExecuteCommandContexts(Uint32 QueueIndex,
177 Uint32 NumContexts,
178 PooledCommandContext pContexts[],
179 bool DiscardStaleObjects,
180 std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>* pSignalFences);
180181
181182 void SignalFences(Uint32 QueueIndex, std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>& SignalFences);
182183
5252 /// Returns the fence value that will be signaled next time
5353 VIRTUAL Uint64 METHOD(GetNextFenceValue)(THIS) CONST PURE;
5454
55 /// Executes a given command list
55 /// Submits command lists for execution.
5656
57 /// \return Fence value associated with the executed command list
57 /// \param[in] NumCommandLists - The number of command lists to submit.
58 /// \param[in] ppCommandLists - A pointer to the array of NumCommandLists command
59 /// lists to submit.
60 ///
61 /// \return Fence value associated with the executed command lists.
5862 VIRTUAL Uint64 METHOD(Submit)(THIS_
59 ID3D12GraphicsCommandList* commandList) PURE;
63 Uint32 NumCommandLists,
64 ID3D12CommandList* const* ppCommandLists) PURE;
6065
6166 /// Returns D3D12 command queue. May return null if queue is anavailable
6267 VIRTUAL ID3D12CommandQueue* METHOD(GetD3D12CommandQueue)(THIS) PURE;
5050 CloseHandle(m_WaitForGPUEventHandle);
5151 }
5252
53 Uint64 CommandQueueD3D12Impl::Submit(ID3D12GraphicsCommandList* commandList)
53 Uint64 CommandQueueD3D12Impl::Submit(Uint32 NumCommandLists,
54 ID3D12CommandList* const* ppCommandLists)
5455 {
5556 std::lock_guard<std::mutex> Lock{m_QueueMtx};
5657
5859 // Increment the value before submitting the list
5960 Atomics::AtomicIncrement(m_NextFenceValue);
6061
61 if (commandList != nullptr)
62 // Render device submits null command list to signal the fence and
63 // discard all resources.
64 if (NumCommandLists != 0 && ppCommandLists != nullptr)
6265 {
63 ID3D12CommandList* const ppCmdLists[] = {commandList};
64 m_pd3d12CmdQueue->ExecuteCommandLists(1, ppCmdLists);
66 #ifdef DILIGENT_DEBUG
67 for (Uint32 i = 0; i < NumCommandLists; ++i)
68 {
69 VERIFY(ppCommandLists[i] != nullptr, "Command list must not be null");
70 }
71 #endif
72 m_pd3d12CmdQueue->ExecuteCommandLists(NumCommandLists, ppCommandLists);
6573 }
6674
6775 // Signal the fence. This must be done atomically with command list submission.
2525 */
2626
2727 #include "pch.h"
28
2829 #include <sstream>
30 #include <vector>
31
2932 #include "RenderDeviceD3D12Impl.hpp"
3033 #include "DeviceContextD3D12Impl.hpp"
3134 #include "PipelineStateD3D12Impl.hpp"
769772 m_CurrCmdCtx->SetDynamicGPUDescriptorAllocators(m_DynamicGPUDescriptorAllocator);
770773 }
771774
772 void DeviceContextD3D12Impl::Flush(bool RequestNewCmdCtx)
773 {
775 void DeviceContextD3D12Impl::Flush(bool RequestNewCmdCtx,
776 Uint32 NumCommandLists,
777 ICommandList* const* ppCommandLists)
778 {
779 VERIFY(!m_bIsDeferred || NumCommandLists == 0 && ppCommandLists == nullptr, "Only immediate context can execute command lists");
780
781 if (m_ActiveQueriesCounter > 0)
782 {
783 LOG_ERROR_MESSAGE("Flushing device context that has ", m_ActiveQueriesCounter,
784 " active queries. Direct3D12 requires that queries are begun and ended in the same command list");
785 }
786
787 // TODO: use small_vector
788 std::vector<RenderDeviceD3D12Impl::PooledCommandContext> Contexts;
789 Contexts.reserve(NumCommandLists + 1);
790
791 // First, execute current context
774792 if (m_CurrCmdCtx)
775793 {
776794 VERIFY(!m_bIsDeferred, "Deferred contexts cannot execute command lists directly");
777795 if (m_State.NumCommands != 0)
778 {
779 m_CurrCmdCtx->FlushResourceBarriers();
780 m_pDevice->CloseAndExecuteCommandContext(m_CommandQueueId, std::move(m_CurrCmdCtx), true, &m_PendingFences);
781 m_PendingFences.clear();
782 }
796 Contexts.emplace_back(std::move(m_CurrCmdCtx));
783797 else
784798 m_pDevice->DisposeCommandContext(std::move(m_CurrCmdCtx));
785799 }
786800
787 if (m_ActiveQueriesCounter > 0)
788 {
789 LOG_ERROR_MESSAGE("Flushing device context that has ", m_ActiveQueriesCounter,
790 " active queries. Direct3D12 requires that queries are begun and ended in the same command list");
801 // Next, add extra command lists from deferred contexts
802 for (Uint32 i = 0; i < NumCommandLists; ++i)
803 {
804 auto* const pCmdListD3D12 = ValidatedCast<CommandListD3D12Impl>(ppCommandLists[i]);
805
806 RefCntAutoPtr<DeviceContextD3D12Impl> pDeferredCtx;
807 Contexts.emplace_back(pCmdListD3D12->Close(pDeferredCtx));
808 // Set the bit in the deferred context cmd queue mask corresponding to the cmd queue of this context
809 pDeferredCtx->m_SubmittedBuffersCmdQueueMask.fetch_or(Uint64{1} << m_CommandQueueId);
810 }
811
812 if (!Contexts.empty())
813 {
814 m_pDevice->CloseAndExecuteCommandContexts(m_CommandQueueId, static_cast<Uint32>(Contexts.size()), Contexts.data(), true, &m_PendingFences);
815 m_PendingFences.clear();
816
817 #ifdef DILIGENT_DEBUG
818 for (Uint32 i = 0; i < NumCommandLists; ++i)
819 VERIFY(!Contexts[i], "All contexts must be disposed by CloseAndExecuteCommandContexts");
820 #endif
791821 }
792822
793823 // If there is no command list to submit, but there are pending fences, we need to signal them now
20312061
20322062 void DeviceContextD3D12Impl::FinishCommandList(ICommandList** ppCommandList)
20332063 {
2034 VERIFY(m_pActiveRenderPass == nullptr, "Finishing command list inside an active render pass.");
2064 DEV_CHECK_ERR(m_pActiveRenderPass == nullptr, "Finishing command list inside an active render pass.");
20352065
20362066 CommandListD3D12Impl* pCmdListD3D12(NEW_RC_OBJ(m_CmdListAllocator, "CommandListD3D12Impl instance", CommandListD3D12Impl)(m_pDevice, this, std::move(m_CurrCmdCtx)));
20372067 pCmdListD3D12->QueryInterface(IID_CommandList, reinterpret_cast<IObject**>(ppCommandList));
20402070 InvalidateState();
20412071 }
20422072
2043 void DeviceContextD3D12Impl::ExecuteCommandList(ICommandList* pCommandList)
2073 void DeviceContextD3D12Impl::ExecuteCommandLists(Uint32 NumCommandLists,
2074 ICommandList* const* ppCommandLists)
20442075 {
20452076 if (m_bIsDeferred)
20462077 {
20472078 LOG_ERROR_MESSAGE("Only immediate context can execute command list");
20482079 return;
20492080 }
2050 // First execute commands in this context
2051 Flush(true);
2081
2082 if (NumCommandLists == 0)
2083 return;
2084 DEV_CHECK_ERR(ppCommandLists != nullptr, "ppCommandLists must not be null when NumCommandLists is not zero");
2085
2086 Flush(true, NumCommandLists, ppCommandLists);
20522087
20532088 InvalidateState();
2054
2055 CommandListD3D12Impl* pCmdListD3D12 = ValidatedCast<CommandListD3D12Impl>(pCommandList);
2056 VERIFY_EXPR(m_PendingFences.empty());
2057 RefCntAutoPtr<DeviceContextD3D12Impl> pDeferredCtx;
2058 auto CmdContext = pCmdListD3D12->Close(pDeferredCtx);
2059 m_pDevice->CloseAndExecuteCommandContext(m_CommandQueueId, std::move(CmdContext), true, nullptr);
2060 // Set the bit in the deferred context cmd queue mask corresponding to cmd queue of this context
2061 pDeferredCtx->m_SubmittedBuffersCmdQueueMask |= Uint64{1} << m_CommandQueueId;
20622089 }
20632090
20642091 void DeviceContextD3D12Impl::SignalFence(IFence* pFence, Uint64 Value)
20652092 {
2066 VERIFY(!m_bIsDeferred, "Fence can only be signaled from immediate context");
2093 DEV_CHECK_ERR(!m_bIsDeferred, "Fence can only be signaled from immediate context");
20672094 m_PendingFences.emplace_back(Value, pFence);
20682095 }
20692096
20702097 void DeviceContextD3D12Impl::WaitForFence(IFence* pFence, Uint64 Value, bool FlushContext)
20712098 {
2072 VERIFY(!m_bIsDeferred, "Fence can only be waited from immediate context");
2099 DEV_CHECK_ERR(!m_bIsDeferred, "Fence can only be waited from immediate context");
20732100 if (FlushContext)
20742101 Flush();
20752102 auto* pFenceD3D12 = ValidatedCast<FenceD3D12Impl>(pFence);
20782105
20792106 void DeviceContextD3D12Impl::WaitForIdle()
20802107 {
2081 VERIFY(!m_bIsDeferred, "Only immediate contexts can be idled");
2108 DEV_CHECK_ERR(!m_bIsDeferred, "Only immediate contexts can be idled");
20822109 Flush();
20832110 m_pDevice->IdleCommandQueue(m_CommandQueueId, true);
20842111 }
2525 */
2626
2727 #include "pch.h"
28
2829 #include <dxgi1_4.h>
30 #include <vector>
31
2932 #include "RenderDeviceD3D12Impl.hpp"
3033 #include "PipelineStateD3D12Impl.hpp"
3134 #include "ShaderD3D12Impl.hpp"
405408 void RenderDeviceD3D12Impl::CloseAndExecuteTransientCommandContext(Uint32 CommandQueueIndex, PooledCommandContext&& Ctx)
406409 {
407410 CComPtr<ID3D12CommandAllocator> pAllocator;
408 ID3D12GraphicsCommandList* pCmdList = Ctx->Close(pAllocator);
409 Uint64 FenceValue = 0;
411 ID3D12CommandList* const pCmdList = Ctx->Close(pAllocator);
412 VERIFY(pCmdList != nullptr, "Command list must not be null");
413 Uint64 FenceValue = 0;
410414 // Execute command list directly through the queue to avoid interference with command list numbers in the queue
411415 LockCmdQueueAndRun(CommandQueueIndex,
412416 [&](ICommandQueueD3D12* pCmdQueue) //
413417 {
414 FenceValue = pCmdQueue->Submit(pCmdList);
418 FenceValue = pCmdQueue->Submit(1, &pCmdList);
415419 });
416420 m_CmdListManager.ReleaseAllocator(std::move(pAllocator), CommandQueueIndex, FenceValue);
417421 FreeCommandContext(std::move(Ctx));
418422 }
419423
420 Uint64 RenderDeviceD3D12Impl::CloseAndExecuteCommandContext(Uint32 QueueIndex, PooledCommandContext&& Ctx, bool DiscardStaleObjects, std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>* pSignalFences)
421 {
422 CComPtr<ID3D12CommandAllocator> pAllocator;
423 ID3D12GraphicsCommandList* pCmdList = Ctx->Close(pAllocator);
424 Uint64 RenderDeviceD3D12Impl::CloseAndExecuteCommandContexts(Uint32 QueueIndex,
425 Uint32 NumContexts,
426 PooledCommandContext pContexts[],
427 bool DiscardStaleObjects,
428 std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>* pSignalFences)
429 {
430 VERIFY_EXPR(NumContexts > 0 && pContexts != 0);
431
432 // TODO: use small_vector
433 std::vector<ID3D12CommandList*> d3d12CmdLists;
434 std::vector<CComPtr<ID3D12CommandAllocator>> CmdAllocators;
435 d3d12CmdLists.reserve(NumContexts);
436 CmdAllocators.reserve(NumContexts);
437
438 for (Uint32 i = 0; i < NumContexts; ++i)
439 {
440 auto& pCtx = pContexts[i];
441 VERIFY_EXPR(pCtx);
442 CComPtr<ID3D12CommandAllocator> pAllocator;
443 d3d12CmdLists.emplace_back(pCtx->Close(pAllocator));
444 CmdAllocators.emplace_back(std::move(pAllocator));
445 }
424446
425447 Uint64 FenceValue = 0;
426448 {
442464 // | N+1, but resource it references | |
443465 // | was added to the delete queue | |
444466 // | with number N | |
445 auto SubmittedCmdBuffInfo = TRenderDeviceBase::SubmitCommandBuffer(QueueIndex, pCmdList, true);
467 auto SubmittedCmdBuffInfo = TRenderDeviceBase::SubmitCommandBuffer(QueueIndex, true, NumContexts, d3d12CmdLists.data());
446468 FenceValue = SubmittedCmdBuffInfo.FenceValue;
447469 if (pSignalFences != nullptr)
448470 SignalFences(QueueIndex, *pSignalFences);
449471 }
450472
451 m_CmdListManager.ReleaseAllocator(std::move(pAllocator), QueueIndex, FenceValue);
452 FreeCommandContext(std::move(Ctx));
473 for (Uint32 i = 0; i < NumContexts; ++i)
474 {
475 m_CmdListManager.ReleaseAllocator(std::move(CmdAllocators[i]), QueueIndex, FenceValue);
476 FreeCommandContext(std::move(pContexts[i]));
477 }
453478
454479 PurgeReleaseQueue(QueueIndex);
455480
476501 {
477502 // Submit empty command list to the queue. This will effectively signal the fence and
478503 // discard all resources
479 ID3D12GraphicsCommandList* pNullCmdList = nullptr;
480 TRenderDeviceBase::SubmitCommandBuffer(CmdQueueIndex, pNullCmdList, true);
504 TRenderDeviceBase::SubmitCommandBuffer(CmdQueueIndex, true, 0, nullptr);
481505 }
482506
483507 void RenderDeviceD3D12Impl::ReleaseStaleResources(bool ForceRelease)
9797 if (this->m_bIsDeferred)
9898 {
9999 // For deferred context, reset submitted cmd queue mask
100 m_SubmittedBuffersCmdQueueMask = 0;
100 m_SubmittedBuffersCmdQueueMask.store(0);
101101 }
102102 else
103103 {
115115 // For deferred contexts, this will accumulate bits of the queues to which command buffers
116116 // were submitted to before FinishFrame() was called. This mask is used to release resources
117117 // allocated by the context during the frame when FinishFrame() is called.
118 Uint64 m_SubmittedBuffersCmdQueueMask = 0;
118 std::atomic_uint64_t m_SubmittedBuffersCmdQueueMask{0};
119119 };
120120
121121 } // namespace Diligent
2828
2929 #include <vector>
3030 #include <mutex>
31 #include <atomic>
3132
3233 #include "EngineFactory.h"
33 #include "Atomics.hpp"
3434 #include "BasicTypes.h"
3535 #include "ReferenceCounters.h"
3636 #include "MemoryAllocator.h"
117117
118118 auto& Queue = m_CommandQueues[QueueIndex];
119119 // Do not use std::move on wrapper!!!
120 Queue.ReleaseQueue.SafeReleaseResource(Wrapper, Queue.NextCmdBufferNumber);
120 Queue.ReleaseQueue.SafeReleaseResource(Wrapper, Queue.NextCmdBufferNumber.load());
121121 QueueMask &= ~(Uint64{1} << Uint64{QueueIndex});
122122 --NumReferences;
123123 }
162162
163163 if (ReleaseResources)
164164 {
165 // Increment command buffer number before idling the queue.
165 // Increment the command buffer number before idling the queue.
166166 // This will make sure that any resource released while this function
167167 // is running will be associated with the next command buffer submission.
168 CmdBufferNumber = static_cast<Uint64>(Queue.NextCmdBufferNumber);
169 Atomics::AtomicIncrement(Queue.NextCmdBufferNumber);
168 CmdBufferNumber = Queue.NextCmdBufferNumber.fetch_add(1);
169 // fetch_add returns the original value immediately preceding the addition.
170170 }
171171
172172 FenceValue = Queue.CmdQueue->WaitForIdle();
190190 Uint64 CmdBufferNumber = 0;
191191 Uint64 FenceValue = 0;
192192 };
193 template <typename SubmitDataType>
194 SubmittedCommandBufferInfo SubmitCommandBuffer(Uint32 QueueIndex, SubmitDataType& SubmitData, bool DiscardStaleResources)
193 template <typename... SubmitDataType>
194 SubmittedCommandBufferInfo SubmitCommandBuffer(Uint32 QueueIndex, bool DiscardStaleResources, const SubmitDataType&... SubmitData)
195195 {
196196 SubmittedCommandBufferInfo CmdBuffInfo;
197197 VERIFY_EXPR(QueueIndex < m_CmdQueueCount);
200200 {
201201 std::lock_guard<std::mutex> Lock{Queue.Mtx};
202202
203 // Increment command buffer number before submitting the cmd buffer.
203 // Increment the command buffer number before submitting the cmd buffer.
204204 // This will make sure that any resource released while this function
205205 // is running will be associated with the next command buffer.
206 CmdBuffInfo.CmdBufferNumber = static_cast<Uint64>(Queue.NextCmdBufferNumber);
207 Atomics::AtomicIncrement(Queue.NextCmdBufferNumber);
208
209 CmdBuffInfo.FenceValue = Queue.CmdQueue->Submit(SubmitData);
206 CmdBuffInfo.CmdBufferNumber = Queue.NextCmdBufferNumber.fetch_add(1);
207 // fetch_add returns the original value immediately preceding the addition.
208
209 CmdBuffInfo.FenceValue = Queue.CmdQueue->Submit(SubmitData...);
210210 }
211211
212212 if (DiscardStaleResources)
303303 CmdQueue{std::move(_CmdQueue)},
304304 ReleaseQueue{Allocator}
305305 {
306 NextCmdBufferNumber = 0;
306 NextCmdBufferNumber.store(0);
307307 }
308308
309309 // clang-format off
314314 // clang-format on
315315
316316 std::mutex Mtx;
317 Atomics::AtomicInt64 NextCmdBufferNumber;
317 std::atomic_uint64_t NextCmdBufferNumber{0};
318318 RefCntAutoPtr<CommandQueueType> CmdQueue;
319319 ResourceReleaseQueue<DynamicStaleResourceWrapper> ReleaseQueue;
320320 };
225225 /// Implementation of IDeviceContext::FinishCommandList() in OpenGL backend.
226226 virtual void DILIGENT_CALL_TYPE FinishCommandList(class ICommandList** ppCommandList) override final;
227227
228 /// Implementation of IDeviceContext::ExecuteCommandList() in OpenGL backend.
229 virtual void DILIGENT_CALL_TYPE ExecuteCommandList(class ICommandList* pCommandList) override final;
228 /// Implementation of IDeviceContext::ExecuteCommandLists() in OpenGL backend.
229 virtual void DILIGENT_CALL_TYPE ExecuteCommandLists(Uint32 NumCommandLists,
230 ICommandList* const* ppCommandLists) override final;
230231
231232 /// Implementation of IDeviceContext::SignalFence() in OpenGL backend.
232233 virtual void DILIGENT_CALL_TYPE SignalFence(IFence* pFence, Uint64 Value) override final;
12811281 LOG_ERROR("Deferred contexts are not supported in OpenGL mode");
12821282 }
12831283
1284 void DeviceContextGLImpl::ExecuteCommandList(class ICommandList* pCommandList)
1284 void DeviceContextGLImpl::ExecuteCommandLists(Uint32 NumCommandLists,
1285 ICommandList* const* ppCommandLists)
12851286 {
12861287 LOG_ERROR("Deferred contexts are not supported in OpenGL mode");
12871288 }
265265 elseif(PLATFORM_MACOS)
266266 # Use Volk
267267 elseif(PLATFORM_IOS)
268 # For the apparent lack of a better way, link with both arm64 and x64 libraries.
269 # The linker will issue a warning, but this will work for both device and the simulator.
270 list(APPEND PRIVATE_DEPENDENCIES
271 "${MoltenVK_FRAMEWORK}/ios-arm64/libMoltenVK.a"
272 "${MoltenVK_FRAMEWORK}/ios-x86_64-simulator/libMoltenVK.a"
273 )
268 if(CMAKE_OSX_SYSROOT STREQUAL "iphonesimulator" OR PLATFORM_IOS_SIMULATOR)
269 list(APPEND PRIVATE_DEPENDENCIES
270 "${MoltenVK_FRAMEWORK}/ios-arm64_x86_64-simulator/libMoltenVK.a"
271 )
272 else()
273 list(APPEND PRIVATE_DEPENDENCIES
274 "${MoltenVK_FRAMEWORK}/ios-arm64/libMoltenVK.a"
275 )
276 endif()
274277
275278 find_library(CORE_GRAPHICS CoreGraphics)
276279 find_library(METAL_LIBRARY Metal)
5959 VERIFY(m_vkCmdBuff == VK_NULL_HANDLE && !m_pDeferredCtx, "Destroying command list that was never executed");
6060 }
6161
62 void Close(VkCommandBuffer& CmdBuff,
63 RefCntAutoPtr<IDeviceContext>& pDeferredCtx)
62 VkCommandBuffer Close(RefCntAutoPtr<IDeviceContext>& pDeferredCtx)
6463 {
65 CmdBuff = m_vkCmdBuff;
66 m_vkCmdBuff = VK_NULL_HANDLE;
67 pDeferredCtx = std::move(m_pDeferredCtx);
64 auto vkCmdBuff = m_vkCmdBuff;
65 m_vkCmdBuff = VK_NULL_HANDLE;
66 pDeferredCtx = std::move(m_pDeferredCtx);
67 return vkCmdBuff;
6868 }
6969
7070 private:
235235 /// Implementation of IDeviceContext::FinishCommandList() in Vulkan backend.
236236 virtual void DILIGENT_CALL_TYPE FinishCommandList(class ICommandList** ppCommandList) override final;
237237
238 /// Implementation of IDeviceContext::ExecuteCommandList() in Vulkan backend.
239 virtual void DILIGENT_CALL_TYPE ExecuteCommandList(class ICommandList* pCommandList) override final;
238 /// Implementation of IDeviceContext::ExecuteCommandLists() in Vulkan backend.
239 virtual void DILIGENT_CALL_TYPE ExecuteCommandLists(Uint32 NumCommandLists,
240 ICommandList* const* ppCommandLists) override final;
240241
241242 /// Implementation of IDeviceContext::SignalFence() in Vulkan backend.
242243 virtual void DILIGENT_CALL_TYPE SignalFence(IFence* pFence, Uint64 Value) override final;
398399 void CommitVkVertexBuffers();
399400 void CommitViewports();
400401 void CommitScissorRects();
402
403 void Flush(Uint32 NumCommandLists,
404 ICommandList* const* ppCommandLists);
401405
402406 __forceinline void TransitionOrVerifyBufferState(BufferVkImpl& Buffer,
403407 RESOURCE_STATE_TRANSITION_MODE TransitionMode,
238238
239239 virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final;
240240
241 // Submits command buffer for execution to the command queue
242 // Returns the submitted command buffer number and the fence value
241 // Submits command buffer(s) for execution to the command queue and
242 // returns the submitted command buffer(s) number and the fence value.
243 // If SubmitInfo contains multiple command buffers, they all are treated
244 // like one and sumbitted atomically.
243245 // Parameters:
244246 // * SubmittedCmdBuffNumber - submitted command buffer number
245247 // * SubmittedFenceValue - fence value associated with the submitted command buffer
246 void SubmitCommandBuffer(Uint32 QueueIndex, const VkSubmitInfo& SubmitInfo, Uint64& SubmittedCmdBuffNumber, Uint64& SubmittedFenceValue, std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>* pFences);
248 void SubmitCommandBuffer(Uint32 QueueIndex,
249 const VkSubmitInfo& SubmitInfo,
250 Uint64& SubmittedCmdBuffNumber,
251 Uint64& SubmittedFenceValue,
252 std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>* pFences);
247253
248254 std::shared_ptr<VulkanUtilities::VulkanInstance> m_VulkanInstance;
249255 std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> m_PhysicalDevice;
2525 */
2626
2727 #include "pch.h"
28
2829 #include <sstream>
30 #include <vector>
31
2932 #include "RenderDeviceVkImpl.hpp"
3033 #include "DeviceContextVkImpl.hpp"
3134 #include "PipelineStateVkImpl.hpp"
12341237
12351238 void DeviceContextVkImpl::Flush()
12361239 {
1240 Flush(0, nullptr);
1241 }
1242
1243 void DeviceContextVkImpl::Flush(Uint32 NumCommandLists,
1244 ICommandList* const* ppCommandLists)
1245 {
12371246 if (m_bIsDeferred)
12381247 {
12391248 LOG_ERROR_MESSAGE("Flush() should only be called for immediate contexts.");
12511260 LOG_ERROR_MESSAGE("Flushing device context inside an active render pass.");
12521261 }
12531262
1254 VkSubmitInfo SubmitInfo = {};
1255
1256 SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1257 SubmitInfo.pNext = nullptr;
1263 // TODO: replace with small_vector
1264 std::vector<VkCommandBuffer> vkCmdBuffs;
1265 std::vector<RefCntAutoPtr<IDeviceContext>> DeferredCtxs;
1266 vkCmdBuffs.reserve(NumCommandLists + 1);
1267 DeferredCtxs.reserve(NumCommandLists + 1);
12581268
12591269 auto vkCmdBuff = m_CommandBuffer.GetVkCmdBuffer();
12601270 if (vkCmdBuff != VK_NULL_HANDLE)
12741284 m_CommandBuffer.FlushBarriers();
12751285 m_CommandBuffer.EndCommandBuffer();
12761286
1277 SubmitInfo.commandBufferCount = 1;
1278 SubmitInfo.pCommandBuffers = &vkCmdBuff;
1279 }
1287 vkCmdBuffs.push_back(vkCmdBuff);
1288 }
1289 }
1290
1291 // Add command buffers from deferred contexts
1292 for (Uint32 i = 0; i < NumCommandLists; ++i)
1293 {
1294 auto* pCmdListVk = ValidatedCast<CommandListVkImpl>(ppCommandLists[i]);
1295 DEV_CHECK_ERR(pCmdListVk != nullptr, "Command list must not be null");
1296 RefCntAutoPtr<IDeviceContext> pDeferredCtx;
1297 vkCmdBuffs.emplace_back(pCmdListVk->Close(pDeferredCtx));
1298 VERIFY(vkCmdBuffs.back() != VK_NULL_HANDLE, "Trying to execute empty command buffer");
1299 VERIFY_EXPR(pDeferredCtx);
1300 DeferredCtxs.emplace_back(std::move(pDeferredCtx));
12801301 }
12811302
12821303 VERIFY_EXPR(m_VkWaitSemaphores.size() == m_WaitSemaphores.size());
12831304 VERIFY_EXPR(m_VkSignalSemaphores.size() == m_SignalSemaphores.size());
12841305
1306 VkSubmitInfo SubmitInfo = {};
1307
1308 SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1309 SubmitInfo.pNext = nullptr;
1310
1311 SubmitInfo.commandBufferCount = static_cast<uint32_t>(vkCmdBuffs.size());
1312 SubmitInfo.pCommandBuffers = vkCmdBuffs.data();
12851313 SubmitInfo.waitSemaphoreCount = static_cast<uint32_t>(m_WaitSemaphores.size());
12861314 VERIFY_EXPR(m_WaitSemaphores.size() == m_WaitDstStageMasks.size());
12871315 SubmitInfo.pWaitSemaphores = SubmitInfo.waitSemaphoreCount != 0 ? m_VkWaitSemaphores.data() : nullptr;
13001328 m_VkSignalSemaphores.clear();
13011329 m_PendingFences.clear();
13021330
1331 size_t buff_idx = 0;
13031332 if (vkCmdBuff != VK_NULL_HANDLE)
13041333 {
1334 VERIFY_EXPR(vkCmdBuffs[buff_idx] == vkCmdBuff);
13051335 DisposeCurrentCmdBuffer(m_CommandQueueId, SubmittedFenceValue);
1306 }
1336 ++buff_idx;
1337 }
1338
1339 for (Uint32 i = 0; i < NumCommandLists; ++i, ++buff_idx)
1340 {
1341 auto pDeferredCtxVkImpl = DeferredCtxs[i].RawPtr<DeviceContextVkImpl>();
1342 // Set the bit in the deferred context cmd queue mask corresponding to cmd queue of this context
1343 pDeferredCtxVkImpl->m_SubmittedBuffersCmdQueueMask.fetch_or(Uint64{1} << m_CommandQueueId);
1344 // It is OK to dispose command buffer from another thread. We are not going to
1345 // record any commands and only need to add the buffer to the queue
1346 pDeferredCtxVkImpl->DisposeVkCmdBuffer(m_CommandQueueId, std::move(vkCmdBuffs[buff_idx]), SubmittedFenceValue);
1347 }
1348 VERIFY_EXPR(buff_idx == vkCmdBuffs.size());
13071349
13081350 for (auto& BindInfo : m_DescrSetBindInfo)
13091351 BindInfo = DescriptorSetBindInfo{};
23772419 InvalidateState();
23782420 }
23792421
2380 void DeviceContextVkImpl::ExecuteCommandList(class ICommandList* pCommandList)
2422 void DeviceContextVkImpl::ExecuteCommandLists(Uint32 NumCommandLists,
2423 ICommandList* const* ppCommandLists)
23812424 {
23822425 if (m_bIsDeferred)
23832426 {
23852428 return;
23862429 }
23872430
2388 Flush();
2431 if (NumCommandLists == 0)
2432 return;
2433 DEV_CHECK_ERR(ppCommandLists != nullptr, "ppCommandLists must not be null when NumCommandLists is not zero");
2434
2435 Flush(NumCommandLists, ppCommandLists);
23892436
23902437 InvalidateState();
2391
2392 CommandListVkImpl* pCmdListVk = ValidatedCast<CommandListVkImpl>(pCommandList);
2393 VkCommandBuffer vkCmdBuff = VK_NULL_HANDLE;
2394
2395 RefCntAutoPtr<IDeviceContext> pDeferredCtx;
2396 pCmdListVk->Close(vkCmdBuff, pDeferredCtx);
2397 VERIFY(vkCmdBuff != VK_NULL_HANDLE, "Trying to execute empty command buffer");
2398 VERIFY_EXPR(pDeferredCtx);
2399 VkSubmitInfo SubmitInfo = {};
2400
2401 SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
2402 SubmitInfo.pNext = nullptr;
2403 SubmitInfo.commandBufferCount = 1;
2404 SubmitInfo.pCommandBuffers = &vkCmdBuff;
2405 VERIFY_EXPR(m_PendingFences.empty());
2406 auto pDeferredCtxVkImpl = pDeferredCtx.RawPtr<DeviceContextVkImpl>();
2407 auto SubmittedFenceValue = m_pDevice->ExecuteCommandBuffer(m_CommandQueueId, SubmitInfo, this, nullptr);
2408 // Set the bit in the deferred context cmd queue mask corresponding to cmd queue of this context
2409 pDeferredCtxVkImpl->m_SubmittedBuffersCmdQueueMask |= Uint64{1} << m_CommandQueueId;
2410 // It is OK to dispose command buffer from another thread. We are not going to
2411 // record any commands and only need to add the buffer to the queue
2412 pDeferredCtxVkImpl->DisposeVkCmdBuffer(m_CommandQueueId, vkCmdBuff, SubmittedFenceValue);
24132438 }
24142439
24152440 void DeviceContextVkImpl::SignalFence(IFence* pFence, Uint64 Value)
4444
4545 namespace Diligent
4646 {
47
48 #if !DILIGENT_NO_HLSL
49 namespace GLSLangUtils
50 {
51 void SpvOptimizerMessageConsumer(
52 spv_message_level_t level,
53 const char* /* source */,
54 const spv_position_t& /* position */,
55 const char* message);
56 }
57 #endif
58
4759 namespace
4860 {
4961
6274 Target = SPV_ENV_VULKAN_1_1_SPIRV_1_4;
6375
6476 spvtools::Optimizer SpirvOptimizer(Target);
77 SpirvOptimizer.SetMessageConsumer(GLSLangUtils::SpvOptimizerMessageConsumer);
6578 // Decorations defined in SPV_GOOGLE_hlsl_functionality1 are the only instructions
6679 // removed by strip-reflect-info pass. SPIRV offsets become INVALID after this operation.
6780 SpirvOptimizer.RegisterPass(spvtools::CreateStripReflectInfoPass());
400400 )
401401 {
402402 // Submit the command list to the queue
403 auto CmbBuffInfo = TRenderDeviceBase::SubmitCommandBuffer(QueueIndex, SubmitInfo, true);
403 auto CmbBuffInfo = TRenderDeviceBase::SubmitCommandBuffer(QueueIndex, true, SubmitInfo);
404404 SubmittedFenceValue = CmbBuffInfo.FenceValue;
405405 SubmittedCmdBuffNumber = CmbBuffInfo.CmdBufferNumber;
406406 if (pFences != nullptr)
444444 // Submit empty command buffer to the queue. This will effectively signal the fence and
445445 // discard all resources
446446 VkSubmitInfo DummySumbitInfo = {};
447 TRenderDeviceBase::SubmitCommandBuffer(0, DummySumbitInfo, true);
447 TRenderDeviceBase::SubmitCommandBuffer(0, true, DummySumbitInfo);
448448 }
449449
450450 void RenderDeviceVkImpl::ReleaseStaleResources(bool ForceRelease)
330330 m_SwapChainDesc.Width = swapchainExtent.width;
331331 m_SwapChainDesc.Height = swapchainExtent.height;
332332
333 // Mailbox is the lowest latency non-tearing presentation mode.
334 VkPresentModeKHR swapchainPresentMode = m_VSyncEnabled ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_MAILBOX_KHR;
335
336 bool PresentModeSupported = std::find(presentModes.begin(), presentModes.end(), swapchainPresentMode) != presentModes.end();
337 if (!PresentModeSupported)
338 {
339 VERIFY(swapchainPresentMode != VK_PRESENT_MODE_FIFO_KHR, "The FIFO present mode is guaranteed by the spec to be supported");
333 // The FIFO present mode is guaranteed by the spec to always be supported.
334 VkPresentModeKHR PresentMode = VK_PRESENT_MODE_FIFO_KHR;
335 {
336 std::vector<VkPresentModeKHR> PreferredPresentModes;
337 if (m_VSyncEnabled)
338 {
339 // FIFO relaxed waits for the next VSync, but if the frame is late,
340 // it still shows it even if VSync has already passed, which may
341 // result in tearing.
342 PreferredPresentModes.push_back(VK_PRESENT_MODE_FIFO_RELAXED_KHR);
343 PreferredPresentModes.push_back(VK_PRESENT_MODE_FIFO_KHR);
344 }
345 else
346 {
347 // Mailbox is the lowest latency non-tearing presentation mode.
348 PreferredPresentModes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
349 PreferredPresentModes.push_back(VK_PRESENT_MODE_IMMEDIATE_KHR);
350 PreferredPresentModes.push_back(VK_PRESENT_MODE_FIFO_KHR);
351 }
352
353 for (auto PreferredMode : PreferredPresentModes)
354 {
355 if (std::find(presentModes.begin(), presentModes.end(), PreferredMode) != presentModes.end())
356 {
357 PresentMode = PreferredMode;
358 break;
359 }
360 }
340361
341362 const char* PresentModeName = nullptr;
342
343363 #define PRESENT_MODE_CASE(Mode) \
344364 case Mode: PresentModeName = #Mode; break;
345 switch (swapchainPresentMode)
365 switch (PresentMode)
346366 {
347367 PRESENT_MODE_CASE(VK_PRESENT_MODE_IMMEDIATE_KHR)
348368 PRESENT_MODE_CASE(VK_PRESENT_MODE_MAILBOX_KHR)
353373 default: PresentModeName = "<UNKNOWN>";
354374 }
355375 #undef PRESENT_MODE_CASE
356 LOG_WARNING_MESSAGE(PresentModeName, " is not supported. Defaulting to VK_PRESENT_MODE_FIFO_KHR");
357
358 swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
359 // The FIFO present mode is guaranteed by the spec to be supported
360 VERIFY(std::find(presentModes.begin(), presentModes.end(), swapchainPresentMode) != presentModes.end(), "FIFO present mode must be supported");
376 LOG_INFO_MESSAGE("Using ", PresentModeName, " swap chain present mode");
361377 }
362378
363379 // Determine the number of VkImage's to use in the swap chain.
416432 swapchain_ci.preTransform = vkPreTransform;
417433 swapchain_ci.compositeAlpha = compositeAlpha;
418434 swapchain_ci.imageArrayLayers = 1;
419 swapchain_ci.presentMode = swapchainPresentMode;
435 swapchain_ci.presentMode = PresentMode;
420436 swapchain_ci.oldSwapchain = oldSwapchain;
421437 swapchain_ci.clipped = VK_TRUE;
422438 swapchain_ci.imageColorSpace = ColorSpace;
151151 }
152152
153153
154 static VkPipelineStageFlags AccessMaskFromImageLayout(VkImageLayout Layout,
155 bool IsDstMask // false - source mask
156 // true - destination mask
154 static VkAccessFlags AccessMaskFromImageLayout(VkImageLayout Layout,
155 bool IsDstMask // false - source mask
156 // true - destination mask
157157 )
158158 {
159 VkPipelineStageFlags AccessMask = 0;
159 VkAccessFlags AccessMask = 0;
160160 switch (Layout)
161161 {
162162 // does not support device access. This layout must only be used as the initialLayout member
99 interface/DurationQueryHelper.hpp
1010 interface/GraphicsUtilities.h
1111 interface/MapHelper.hpp
12 interface/pch.h
1312 interface/ScopedQueryHelper.hpp
1413 interface/ScreenCapture.hpp
1514 interface/ShaderMacroHelper.hpp
2625 src/GraphicsUtilities.cpp
2726 src/ScopedQueryHelper.cpp
2827 src/ScreenCapture.cpp
29 src/pch.cpp
3028 src/TextureUploader.cpp
3129 )
3230
+0
-28
Graphics/GraphicsTools/interface/pch.h less more
0 /*
1 * Copyright 2019-2021 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
2424 * of the possibility of such damages.
2525 */
2626
27 #include "pch.h"
2827 #include "DurationQueryHelper.hpp"
2928
3029 namespace Diligent
2424 * of the possibility of such damages.
2525 */
2626
27 #include "pch.h"
2827 #include <algorithm>
2928 #include <cmath>
3029
2424 * of the possibility of such damages.
2525 */
2626
27 #include "pch.h"
2827 #include "ScopedQueryHelper.hpp"
2928
3029 namespace Diligent
2424 * of the possibility of such damages.
2525 */
2626
27 #include "pch.h"
2827 #include "ScreenCapture.hpp"
2928
3029 namespace Diligent
2424 * of the possibility of such damages.
2525 */
2626
27 #include "pch.h"
2827 #if D3D11_SUPPORTED
2928 # include "TextureUploaderD3D11.hpp"
3029 #endif
2424 * of the possibility of such damages.
2525 */
2626
27 #include "pch.h"
28
2927 #include <unordered_map>
3028 #include <deque>
3129 #include <mutex>
2424 * of the possibility of such damages.
2525 */
2626
27 #include "pch.h"
2827 #include <mutex>
2928 #include <deque>
3029 #include <unordered_map>
+0
-28
Graphics/GraphicsTools/src/pch.cpp less more
0 /*
1 * Copyright 2019-2021 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #include "pch.h"
167167
168168 struct HLSLObjectInfo
169169 {
170 String GLSLType; // sampler2D, sampler2DShadow, image2D, etc.
171 Uint32 NumComponents; // 0,1,2,3 or 4
172 // Texture2D<float4> -> 4
173 // Texture2D<uint> -> 1
174 // Texture2D -> 0
175 HLSLObjectInfo(const String& Type, Uint32 NComp) :
170 const String GLSLType; // sampler2D, sampler2DShadow, image2D, etc.
171
172 const Uint32 NumComponents; // 0, 1, 2, 3 or 4
173 // Texture2D<float4> -> 4
174 // Texture2D<uint> -> 1
175 // Texture2D -> 0
176
177 const Uint32 ArrayDim; // Array dimensionality
178 // Texture2D g_Tex -> 0
179 // Texture2D g_Tex[8] -> 1
180 // Texture2D g_Tex[8][2] -> 2
181 HLSLObjectInfo(const String& Type, Uint32 NComp, Uint32 ArrDim) :
176182 GLSLType{Type},
177 NumComponents{NComp}
183 NumComponents{NComp},
184 ArrayDim{ArrDim}
178185 {}
179186 };
180187 struct ObjectsTypeHashType
350357 const TokenListType::iterator& ScopeEnd);
351358
352359 Uint32 CountFunctionArguments(TokenListType::iterator& Token, const TokenListType::iterator& ScopeEnd);
353 bool ProcessRWTextureStore(TokenListType::iterator& Token, const TokenListType::iterator& ScopeEnd);
360 bool ProcessRWTextureStore(TokenListType::iterator& Token, const TokenListType::iterator& ScopeEnd, Uint32 ArrayDim);
361 bool ProcessRWTextureLoad(TokenListType::iterator& Token, const TokenListType::iterator& ScopeEnd, Uint32 ArrayDim);
354362 void RemoveFlowControlAttribute(TokenListType::iterator& Token);
355363 void RemoveSemantics();
356364 void RemoveSpecialShaderAttributes();
486494 String& Globals,
487495 String& Prologue);
488496
489 void FindClosingBracket(TokenListType::iterator& Token,
490 const TokenListType::iterator& ScopeEnd,
491 TokenType OpenBracketType,
492 TokenType ClosingBracketType);
497 void FindMatchingBracket(TokenListType::iterator& Token,
498 const TokenListType::iterator& ScopeEnd,
499 TokenType OpenBracketType);
493500
494501 void ProcessReturnStatements(TokenListType::iterator& Token,
495502 bool IsVoid,
13711371 }
13721372
13731373
1374 void HLSL2GLSLConverterImpl::ConversionStream::FindClosingBracket(TokenListType::iterator& Token,
1375 const TokenListType::iterator& ScopeEnd,
1376 TokenType OpenBracketType,
1377 TokenType ClosingBracketType)
1378 {
1379 VERIFY_EXPR(Token->Type == OpenBracketType);
1380 ++Token; // Skip open bracket
1374 // Searches for the matching bracket.
1375 // For open brackets, searches in the forward direction.
1376 // For closing brackets, searches backwards.
1377 void HLSL2GLSLConverterImpl::ConversionStream::FindMatchingBracket(TokenListType::iterator& Token,
1378 const TokenListType::iterator& ScopeEnd,
1379 TokenType OpenBracketType)
1380 {
1381 VERIFY_EXPR(OpenBracketType == Token->Type);
1382 auto ClosingBracketType = TokenType::Undefined;
1383 int Direction = 0;
1384 switch (OpenBracketType)
1385 {
1386 case TokenType::OpenBrace:
1387 ClosingBracketType = TokenType::ClosingBrace;
1388 Direction = +1;
1389 break;
1390
1391 case TokenType::OpenBracket:
1392 ClosingBracketType = TokenType::ClosingBracket;
1393 Direction = +1;
1394 break;
1395
1396 case TokenType::OpenStaple:
1397 ClosingBracketType = TokenType::ClosingStaple;
1398 Direction = +1;
1399 break;
1400
1401 case TokenType::OpenAngleBracket:
1402 ClosingBracketType = TokenType::ClosingAngleBracket;
1403 Direction = +1;
1404 break;
1405
1406 case TokenType::ClosingBrace:
1407 ClosingBracketType = TokenType::OpenBrace;
1408 Direction = -1;
1409 break;
1410
1411 case TokenType::ClosingBracket:
1412 ClosingBracketType = TokenType::OpenBracket;
1413 Direction = -1;
1414 break;
1415
1416 case TokenType::ClosingStaple:
1417 ClosingBracketType = TokenType::OpenStaple;
1418 Direction = -1;
1419 break;
1420
1421 case TokenType::ClosingAngleBracket:
1422 ClosingBracketType = TokenType::OpenAngleBracket;
1423 Direction = -1;
1424 break;
1425
1426 default:
1427 UNEXPECTED("One of the bracket types is expected");
1428 return;
1429 }
1430 VERIFY_EXPR(Direction != 0);
1431
1432 (Direction > 0 ? ++Token : --Token); // Skip open bracket
13811433 int BracketCount = 1;
1382 // Find matching closing bracket
1434 // Find the matching bracket
13831435 while (Token != ScopeEnd)
13841436 {
13851437 if (Token->Type == OpenBracketType)
13901442 if (BracketCount == 0)
13911443 break;
13921444 }
1393 ++Token;
1445 (Direction > 0 ? ++Token : --Token);
13941446 }
13951447 VERIFY_PARSER_STATE(Token, BracketCount == 0, "No matching closing bracket found in the scope");
13961448 }
14421494 VERIFY_PARSER_STATE(Token, Token != m_Tokens.end(), "Missing open brace in the definition of cbuffer ", CBufferName);
14431495
14441496 // Find closing brace
1445 FindClosingBracket(Token, m_Tokens.end(), TokenType::OpenBrace, TokenType::ClosingBrace);
1497 FindMatchingBracket(Token, m_Tokens.end(), TokenType::OpenBrace);
14461498
14471499 VERIFY_PARSER_STATE(Token, Token != m_Tokens.end(), "No matching closing brace found in the definition of cbuffer ", CBufferName);
14481500 ++Token; // Skip closing brace
15801632 VERIFY_PARSER_STATE(Token, Token != m_Tokens.end() && Token->Type == TokenType::OpenBrace, "Open brace expected");
15811633
15821634 // Find closing brace
1583 FindClosingBracket(Token, m_Tokens.end(), TokenType::OpenBrace, TokenType::ClosingBrace);
1635 FindMatchingBracket(Token, m_Tokens.end(), TokenType::OpenBrace);
15841636 VERIFY_PARSER_STATE(Token, Token != m_Tokens.end(), "Missing closing brace for structure \"", StructName, "\"");
15851637 // }
15861638 // ^
18361888
18371889 ++Token;
18381890 CHECK_EOF();
1891
1892 if (Token->Type == TokenType::kw_unorm)
1893 {
1894 // RWTexture2D < unorm float4 > ... ;
1895 // ^
1896 ++Token;
1897 CHECK_EOF();
1898 }
1899
18391900 // Texture2D < float > ... ;
18401901 // ^
18411902 auto TexFmtToken = Token;
19902051 // Texture2D TexName ;
19912052 // ^
19922053 const auto& TextureName = Token->Literal;
2054
2055 // Determine resource array dimensionality
2056 Uint32 ArrayDim = 0;
2057 {
2058 auto TmpToken = Token;
2059 ++TmpToken;
2060 while (TmpToken != m_Tokens.end() && TmpToken->Type == TokenType::OpenStaple)
2061 {
2062 // Texture2D TexName[...][...]
2063 // ^
2064 FindMatchingBracket(TmpToken, m_Tokens.end(), TokenType::OpenStaple);
2065 // Texture2D TexName[...][...]
2066 // ^
2067
2068 ++ArrayDim;
2069
2070 ++TmpToken;
2071 // Texture2D TexName[...][...]
2072 // ^
2073 }
2074 }
19932075
19942076 auto CompleteGLSLSampler = GLSLSampler;
19952077 if (!IsRWTexture)
20292111 TexDeclToken->Literal.append("IMAGE_WRITEONLY "); // defined as 'writeonly' on GLES and as '' on desktop in GLSLDefinitions.h
20302112 }
20312113 TexDeclToken->Literal.append(CompleteGLSLSampler);
2032 Objects.m.insert(std::make_pair(HashMapStringKey(TextureName), HLSLObjectInfo(CompleteGLSLSampler, NumComponents)));
2114 Objects.m.insert(std::make_pair(HashMapStringKey(TextureName), HLSLObjectInfo{std::move(CompleteGLSLSampler), NumComponents, ArrayDim}));
20332115
20342116 // In global scope, multiple variables can be declared in the same statement
20352117 if (IsGlobalScope)
21722254 // m_Tokens contains dummy node at the beginning, so we can
21732255 // check for ScopeStart to break the loop
21742256 while (IdentifierToken != ScopeStart && IdentifierToken->Type != TokenType::Identifier)
2257 {
21752258 --IdentifierToken;
2259 if (IdentifierToken->Type == TokenType::ClosingAngleBracket ||
2260 IdentifierToken->Type == TokenType::ClosingStaple ||
2261 IdentifierToken->Type == TokenType::ClosingBracket)
2262 {
2263 // TestText[idx[0]].Sample( ...
2264 // ^
2265 FindMatchingBracket(IdentifierToken, ScopeStart, IdentifierToken->Type);
2266 // TestText[idx[0]].Sample( ...
2267 // ^
2268 }
2269 }
21762270 if (IdentifierToken == ScopeStart)
21772271 return false;
21782272 // TestTextArr[2].Sample( ...
23912485 // The function processes HLSL RW texture operator [] and replaces it with
23922486 // corresponding imageStore GLSL function.
23932487 // Example:
2394 // RWTex[Location] = f3Value -> imageStore( RWTex,Location, _ExpandVector(f3Value))
2488 // RWTex[Location] = f3Value -> imageStore( RWTex,_ToIvec(Location), _ExpandVector(f3Value))
23952489 // _ExpandVector() function expands any input vector to 4-component vector
23962490 bool HLSL2GLSLConverterImpl::ConversionStream::ProcessRWTextureStore(TokenListType::iterator& Token,
2397 const TokenListType::iterator& ScopeEnd)
2398 {
2399 // RWTex[Location.x] = float4(0.0, 0.0, 0.0, 1.0);
2491 const TokenListType::iterator& ScopeEnd,
2492 Uint32 ArrayDim)
2493 {
2494 // RWTex[Location.xy] = float4(0.0, 0.0, 0.0, 1.0);
24002495 // ^
2401 auto AssignmentToken = Token;
2402 while (AssignmentToken != ScopeEnd &&
2403 !(AssignmentToken->Type == TokenType::Assignment || AssignmentToken->Type == TokenType::Semicolon))
2404 ++AssignmentToken;
2405
2406 // The function is called for ALL RW texture objects found, so this may not be
2407 // the store operation, but something else (for instance:
2408 // InterlockedExchange(Tex2D_I1[GTid.xy], 1, iOldVal) )
2496
2497 // Find the last pair of square brackets, skipping texture array indexing
2498 auto OpenStapleToken = Token;
2499 auto ClosingStapleToken = ScopeEnd;
2500 for (Uint32 ArrayIdx = 0; ArrayIdx < ArrayDim + 1; ++ArrayIdx)
2501 {
2502 ++OpenStapleToken;
2503 if (OpenStapleToken == ScopeEnd || OpenStapleToken->Type != TokenType::OpenStaple)
2504 return false;
2505
2506 ClosingStapleToken = OpenStapleToken;
2507 FindMatchingBracket(ClosingStapleToken, ScopeEnd, TokenType::OpenStaple);
2508 // RWTex[Location[idx].xy]
2509 // ^
2510 // ClosingStapleToken
2511 VERIFY_EXPR(ClosingStapleToken->Type == TokenType::ClosingStaple);
2512
2513 if (ArrayIdx < ArrayDim)
2514 {
2515 OpenStapleToken = ClosingStapleToken;
2516 // RWTexArray[idx[0]][Location.xy]
2517 // ^
2518 // OpenStapleToken
2519 }
2520 }
2521 // RWTex[Location.xy] = float4(0.0, 0.0, 0.0, 1.0);
2522 // ^ ^
2523 // OpenStaplePos ClosingStaplePos
2524
2525 auto AssignmentToken = ClosingStapleToken;
2526 ++AssignmentToken;
2527
24092528 if (AssignmentToken == ScopeEnd || AssignmentToken->Type != TokenType::Assignment)
2529 {
2530 // The function is called for ALL RW texture objects found, so this may not be
2531 // the store operation, but something else (for instance:
2532 // InterlockedExchange(Tex2D_I1[GTid.xy], 1, iOldVal) )
24102533 return false;
2411 // RWTex[Location.x] = float4(0.0, 0.0, 0.0, 1.0);
2412 // ^
2413 // AssignmentToken
2414 auto ClosingStaplePos = AssignmentToken;
2415 while (ClosingStaplePos != Token && ClosingStaplePos->Type != TokenType::ClosingStaple)
2416 --ClosingStaplePos;
2417 if (ClosingStaplePos == Token)
2418 return false;
2419 // RWTex[Location.x] = float4(0.0, 0.0, 0.0, 1.0);
2420 // ^
2421 // ClosingStaplePos
2422
2423 auto OpenStaplePos = ClosingStaplePos;
2424 while (OpenStaplePos != Token && OpenStaplePos->Type != TokenType::OpenStaple)
2425 --OpenStaplePos;
2426 if (OpenStaplePos == Token)
2427 return false;
2428 // RWTex[Location.x] = float4(0.0, 0.0, 0.0, 1.0);
2429 // ^
2430 // OpenStaplePos
2534 }
2535
2536 // RWTex[Location.xy] = float4(0.0, 0.0, 0.0, 1.0);
2537 // ^
2538 // AssignmentToken
24312539
24322540 auto SemicolonToken = AssignmentToken;
24332541 while (SemicolonToken != ScopeEnd && SemicolonToken->Type != TokenType::Semicolon)
24342542 ++SemicolonToken;
24352543 if (SemicolonToken == ScopeEnd)
24362544 return false;
2437 // RWTex[Location.x] = float4(0.0, 0.0, 0.0, 1.0);
2438 // ^ ^
2545 // RWTex[Location.xy] = float4(0.0, 0.0, 0.0, 1.0);
2546 // ^ ^
24392547 // Token SemicolonToken
24402548
24412549 m_Tokens.insert(Token, TokenInfo(TokenType::Identifier, "imageStore", Token->Delimiter.c_str()));
24422550 m_Tokens.insert(Token, TokenInfo(TokenType::OpenBracket, "(", ""));
24432551 Token->Delimiter = " ";
2444 // imageStore( RWTex[Location.x] = float4(0.0, 0.0, 0.0, 1.0);
2445
2446 OpenStaplePos->Delimiter = "";
2447 OpenStaplePos->Type = TokenType::Comma;
2448 OpenStaplePos->Literal = ",";
2449 // imageStore( RWTex,Location.x] = float4(0.0, 0.0, 0.0, 1.0);
2450 // ^
2451 // ClosingStaplePos
2452
2453 auto LocationToken = OpenStaplePos;
2552 // imageStore( RWTex[Location.xy] = float4(0.0, 0.0, 0.0, 1.0);
2553 // ^ ^
2554 // Token OpenStapleToken
2555
2556 OpenStapleToken->Delimiter = "";
2557 OpenStapleToken->Type = TokenType::Comma;
2558 OpenStapleToken->Literal = ",";
2559 // imageStore( RWTex,Location.xy] = float4(0.0, 0.0, 0.0, 1.0);
2560 // ^ ^
2561 // OpenStapleToken ClosingStapleToken
2562
2563 auto LocationToken = OpenStapleToken;
24542564 ++LocationToken;
24552565 m_Tokens.insert(LocationToken, TokenInfo(TokenType::Identifier, "_ToIvec", " "));
24562566 m_Tokens.insert(LocationToken, TokenInfo(TokenType::OpenBracket, "(", ""));
2457 // imageStore( RWTex, _ToIvec(Location.x] = float4(0.0, 0.0, 0.0, 1.0);
2458 // ^
2459 // ClosingStaplePos
2460
2461 m_Tokens.insert(ClosingStaplePos, TokenInfo(TokenType::ClosingBracket, ")", ""));
2462 // imageStore( RWTex, _ToIvec(Location.x)] = float4(0.0, 0.0, 0.0, 1.0);
2463 // ^
2464 // ClosingStaplePos
2465
2466 ClosingStaplePos->Delimiter = "";
2467 ClosingStaplePos->Type = TokenType::Comma;
2468 ClosingStaplePos->Literal = ",";
2469 // imageStore( RWTex, _ToIvec(Location.x), = float4(0.0, 0.0, 0.0, 1.0);
2470 // ^
2567 // imageStore( RWTex, _ToIvec(Location.xy] = float4(0.0, 0.0, 0.0, 1.0);
2568 // ^ ^
2569 // LocationToken ClosingStapleToken
2570
2571 m_Tokens.insert(ClosingStapleToken, TokenInfo(TokenType::ClosingBracket, ")", ""));
2572 // imageStore( RWTex, _ToIvec(Location.xy)] = float4(0.0, 0.0, 0.0, 1.0);
2573 // ^
2574 // ClosingStapleToken
2575
2576 ClosingStapleToken->Delimiter = "";
2577 ClosingStapleToken->Type = TokenType::Comma;
2578 ClosingStapleToken->Literal = ",";
2579 // imageStore( RWTex, _ToIvec(Location.xy), = float4(0.0, 0.0, 0.0, 1.0);
2580 // ^
24712581 // AssignmentToken
24722582
24732583 AssignmentToken->Delimiter = "";
24742584 AssignmentToken->Type = TokenType::OpenBracket;
24752585 AssignmentToken->Literal = "(";
2476 // imageStore( RWTex, _ToIvec(Location.x),( float4(0.0, 0.0, 0.0, 1.0);
2477 // ^
2586 // imageStore( RWTex, _ToIvec(Location.xy),( float4(0.0, 0.0, 0.0, 1.0);
2587 // ^
2588 // AssignmentToken
24782589
24792590 m_Tokens.insert(AssignmentToken, TokenInfo(TokenType::Identifier, "_ExpandVector", " "));
2480 // imageStore( RWTex, _ToIvec(Location.x), _ExpandVector( float4(0.0, 0.0, 0.0, 1.0);
2481 // ^
2591 // imageStore( RWTex, _ToIvec(Location.xy), _ExpandVector( float4(0.0, 0.0, 0.0, 1.0);
2592 // ^ ^
2593 // AssignmentToken SemicolonToken
24822594
24832595 // Insert closing bracket for _ExpandVector
24842596 m_Tokens.insert(SemicolonToken, TokenInfo(TokenType::ClosingBracket, ")", ""));
2485 // imageStore( RWTex, _ToIvec(Location.x), _ExpandVector( float4(0.0, 0.0, 0.0, 1.0));
2597 // imageStore( RWTex, _ToIvec(Location.xy), _ExpandVector( float4(0.0, 0.0, 0.0, 1.0));
2598 // ^
2599 // SemicolonToken
24862600
24872601 // Insert closing bracket for imageStore
24882602 m_Tokens.insert(SemicolonToken, TokenInfo(TokenType::ClosingBracket, ")", ""));
2489 // imageStore( RWTex, _ToIvec(Location.x), _ExpandVector( float4(0.0, 0.0, 0.0, 1.0)));
2490
2491 return false;
2492 }
2493
2494 // Function finds all RW textures in current scope and calls ProcessRWTextureStore()
2495 // that detects if this is store operation and converts it to imageStore()
2603 // imageStore( RWTex, _ToIvec(Location.xy), _ExpandVector( float4(0.0, 0.0, 0.0, 1.0)));
2604 // ^
2605 // SemicolonToken
2606
2607 Token = LocationToken;
2608 // imageStore( RWTex, _ToIvec(Location.xy), _ExpandVector( float4(0.0, 0.0, 0.0, 1.0)));
2609 // ^
2610
2611 // Note that 'Location' may require further processing as it itself may be e.g. image load operation
2612
2613 return true;
2614 }
2615
2616 // The function processes HLSL RW texture operator [] and replaces it with
2617 // corresponding imageLoad GLSL function.
2618 // Example:
2619 // RWTex[Location] -> imageLoad( RWTex,_ToIvec(Location))
2620 bool HLSL2GLSLConverterImpl::ConversionStream::ProcessRWTextureLoad(TokenListType::iterator& Token,
2621 const TokenListType::iterator& ScopeEnd,
2622 Uint32 ArrayDim)
2623 {
2624 // RWTex[Location.xy]
2625 // ^
2626
2627 // Find the last pair of square brackets, skipping texture array indexing
2628 auto OpenStapleToken = Token;
2629 auto ClosingStapleToken = ScopeEnd;
2630 for (Uint32 ArrayIdx = 0; ArrayIdx < ArrayDim + 1; ++ArrayIdx)
2631 {
2632 ++OpenStapleToken;
2633 if (OpenStapleToken == ScopeEnd || OpenStapleToken->Type != TokenType::OpenStaple)
2634 return false;
2635
2636 ClosingStapleToken = OpenStapleToken;
2637 FindMatchingBracket(ClosingStapleToken, ScopeEnd, TokenType::OpenStaple);
2638 // RWTex[Location[idx].xy]
2639 // ^
2640 // ClosingStapleToken
2641 VERIFY_EXPR(ClosingStapleToken->Type == TokenType::ClosingStaple);
2642
2643 if (ArrayIdx < ArrayDim)
2644 {
2645 OpenStapleToken = ClosingStapleToken;
2646 // RWTexArray[idx[0]][Location.xy]
2647 // ^
2648 // OpenStapleToken
2649 }
2650 }
2651 // RWTex[Location.xy]
2652 // ^ ^
2653 // OpenStaplePos ClosingStaplePos
2654
2655 m_Tokens.insert(Token, TokenInfo(TokenType::Identifier, "imageLoad", Token->Delimiter.c_str()));
2656 m_Tokens.insert(Token, TokenInfo(TokenType::OpenBracket, "(", ""));
2657 Token->Delimiter = " ";
2658 // imageLoad( RWTex[Location.xy]
2659 // ^ ^
2660 // Token OpenStaplePos
2661
2662 m_Tokens.insert(OpenStapleToken, TokenInfo(TokenType::Comma, ",", ""));
2663 m_Tokens.insert(OpenStapleToken, TokenInfo(TokenType::Identifier, "_ToIvec", " "));
2664 // imageLoad( RWTex, _ToIvec[Location.xy]
2665 // ^
2666 // OpenStapleToken
2667
2668 OpenStapleToken->Type = TokenType::OpenBracket;
2669 OpenStapleToken->Literal = "(";
2670 // imageLoad( RWTex, _ToIvec(Location.xy]
2671 // ^ ^
2672 // OpenStapleToken ClosingStapleToken
2673
2674 m_Tokens.insert(ClosingStapleToken, TokenInfo(TokenType::ClosingBracket, ")", ""));
2675 // imageLoad( RWTex, _ToIvec(Location.xy)]
2676 // ^
2677 // ClosingStapleToken
2678
2679
2680 ClosingStapleToken->Type = TokenType::ClosingBracket;
2681 ClosingStapleToken->Literal = ")";
2682 // imageLoad( RWTex, _ToIvec(Location.xy))
2683 // ^
2684 // OpenStapleToken
2685
2686 Token = OpenStapleToken;
2687
2688 // Note that 'Location' may require furhter conversion
2689
2690 return true;
2691 }
2692
2693 // Function finds and processes all RW texture loads and stores in the current scope
24962694 void HLSL2GLSLConverterImpl::ConversionStream::ProcessRWTextures(const TokenListType::iterator& ScopeStart,
24972695 const TokenListType::iterator& ScopeEnd)
24982696 {
25172715 continue;
25182716 }
25192717
2520 // Handle store. If this is not store operation,
2521 // ProcessRWTextureStore() returns false.
2522 auto TmpToken = Token;
2523 if (ProcessRWTextureStore(TmpToken, ScopeEnd))
2524 Token = TmpToken;
2525 else
2526 ++Token;
2718 {
2719 // Handle store first. If this is not a store operation,
2720 // ProcessRWTextureStore() returns false.
2721 auto TmpToken = Token;
2722 if (ProcessRWTextureStore(TmpToken, ScopeEnd, pObjectInfo->ArrayDim))
2723 {
2724 Token = TmpToken;
2725 continue;
2726 }
2727 }
2728
2729 {
2730 // Handle load.
2731 auto TmpToken = Token;
2732 if (ProcessRWTextureLoad(TmpToken, ScopeEnd, pObjectInfo->ArrayDim))
2733 {
2734 Token = TmpToken;
2735 continue;
2736 }
2737 }
2738
2739 ++Token;
25272740 }
25282741 else
25292742 ++Token;
48695082
48705083 ProcessObjectMethods(FunctionStart, Token);
48715084
5085 // Process atomic operations
5086 // InterlockedAdd(RWTex[GTid.xy], 1, iOldVal) -> InterlockedAddImage_3(RWTex,GTid.xy, 1, iOldVal)
5087 ProcessAtomics(FunctionStart, Token);
5088
5089 // Process loads and stores
5090 // RWTex[GTid.xy] = f3Value -> imageStore( RWTex,GTid.xy, _ExpandVector(f3Value))
5091 // RWTex[GTid.xy] -> imageLoad(RWTex,GTid.xy)
48725092 ProcessRWTextures(FunctionStart, Token);
4873
4874 ProcessAtomics(FunctionStart, Token);
48755093
48765094 // Pop function arguments from the sampler and object
48775095 // stacks
6767 ::glslang::FinalizeProcess();
6868 }
6969
70 static EShLanguage ShaderTypeToShLanguage(SHADER_TYPE ShaderType)
70 namespace
71 {
72
73 EShLanguage ShaderTypeToShLanguage(SHADER_TYPE ShaderType)
7174 {
7275 static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please handle the new shader type in the switch below");
7376 switch (ShaderType)
9497 }
9598 }
9699
97 static TBuiltInResource InitResources()
100 TBuiltInResource InitResources()
98101 {
99102 TBuiltInResource Resources;
100103
323326 }
324327 };
325328
326 static void LogCompilerError(const char* DebugOutputMessage,
327 const char* InfoLog,
328 const char* InfoDebugLog,
329 const char* ShaderSource,
330 size_t SourceCodeLen,
331 IDataBlob** ppCompilerOutput)
329 void LogCompilerError(const char* DebugOutputMessage,
330 const char* InfoLog,
331 const char* InfoDebugLog,
332 const char* ShaderSource,
333 size_t SourceCodeLen,
334 IDataBlob** ppCompilerOutput)
332335 {
333336 std::string ErrorLog(InfoLog);
334337 if (*InfoDebugLog != '\0')
348351 }
349352 }
350353
351 static std::vector<unsigned int> CompileShaderInternal(::glslang::TShader& Shader,
352 EShMessages messages,
353 ::glslang::TShader::Includer* pIncluder,
354 const char* ShaderSource,
355 size_t SourceCodeLen,
356 IDataBlob** ppCompilerOutput)
354 std::vector<unsigned int> CompileShaderInternal(::glslang::TShader& Shader,
355 EShMessages messages,
356 ::glslang::TShader::Includer* pIncluder,
357 const char* ShaderSource,
358 size_t SourceCodeLen,
359 IDataBlob** ppCompilerOutput)
357360 {
358361 Shader.setAutoMapBindings(true);
359362 TBuiltInResource Resources = InitResources();
444447 std::unordered_map<IncludeResult*, RefCntAutoPtr<IDataBlob>> m_DataBlobs;
445448 };
446449
450 } // namespace
451
452 void SpvOptimizerMessageConsumer(
453 spv_message_level_t level,
454 const char* /* source */,
455 const spv_position_t& /* position */,
456 const char* message)
457 {
458 const char* LevelText = "message";
459 DEBUG_MESSAGE_SEVERITY MsgSeverity = DEBUG_MESSAGE_SEVERITY_INFO;
460 switch (level)
461 {
462 case SPV_MSG_FATAL:
463 // Unrecoverable error due to environment (e.g. out of memory)
464 LevelText = "fatal error";
465 MsgSeverity = DEBUG_MESSAGE_SEVERITY_FATAL_ERROR;
466 break;
467
468 case SPV_MSG_INTERNAL_ERROR:
469 // Unrecoverable error due to SPIRV-Tools internals (e.g. unimplemented feature)
470 LevelText = "internal error";
471 MsgSeverity = DEBUG_MESSAGE_SEVERITY_ERROR;
472 break;
473
474 case SPV_MSG_ERROR:
475 // Normal error due to user input.
476 LevelText = "error";
477 MsgSeverity = DEBUG_MESSAGE_SEVERITY_ERROR;
478 break;
479
480 case SPV_MSG_WARNING:
481 LevelText = "warning";
482 MsgSeverity = DEBUG_MESSAGE_SEVERITY_WARNING;
483 break;
484
485 case SPV_MSG_INFO:
486 LevelText = "info";
487 MsgSeverity = DEBUG_MESSAGE_SEVERITY_INFO;
488 break;
489
490 case SPV_MSG_DEBUG:
491 LevelText = "debug";
492 MsgSeverity = DEBUG_MESSAGE_SEVERITY_INFO;
493 break;
494 }
495
496 if (level == SPV_MSG_FATAL || level == SPV_MSG_INTERNAL_ERROR || level == SPV_MSG_ERROR || level == SPV_MSG_WARNING)
497 LOG_DEBUG_MESSAGE(MsgSeverity, "Spirv optimizer ", LevelText, ": ", message);
498 }
499
447500 std::vector<unsigned int> HLSLtoSPIRV(const ShaderCreateInfo& ShaderCI,
448501 const char* ExtraDefinitions,
449502 IDataBlob** ppCompilerOutput)
497550
498551 // SPIR-V bytecode generated from HLSL must be legalized to
499552 // turn it into a valid vulkan SPIR-V shader
500 spvtools::Optimizer SpirvOptimizer(SPV_ENV_VULKAN_1_0);
553 spvtools::Optimizer SpirvOptimizer{SPV_ENV_VULKAN_1_0};
554 SpirvOptimizer.SetMessageConsumer(SpvOptimizerMessageConsumer);
501555 SpirvOptimizer.RegisterLegalizationPasses();
502556 SpirvOptimizer.RegisterPerformancePasses();
503557 std::vector<uint32_t> LegalizedSPIRV;
573627 return SPIRV;
574628
575629 spvtools::Optimizer SpirvOptimizer(spvTarget);
630 SpirvOptimizer.SetMessageConsumer(SpvOptimizerMessageConsumer);
576631 SpirvOptimizer.RegisterPerformancePasses();
577632 std::vector<uint32_t> OptimizedSPIRV;
578633 if (SpirvOptimizer.Run(SPIRV.data(), SPIRV.size(), &OptimizedSPIRV))
1616 [![Chat on gitter](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/diligent-engine)
1717 [![Chat on Discord](https://img.shields.io/discord/730091778081947680?logo=discord)](https://discord.gg/t7HGBK7)
1818 [![Codacy Badge](https://api.codacy.com/project/badge/Grade/bb1c00eacb1740d68339d3a45f4c5756)](https://www.codacy.com/manual/DiligentGraphics/DiligentCore?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=DiligentGraphics/DiligentCore&amp;utm_campaign=Badge_Grade)
19 [![Lines of Code](https://tokei.rs/b1/github.com/DiligentGraphics/DiligentCore)](https://github.com/DiligentGraphics/DiligentCore)
20
1921
2022 # Table of Contents
2123
00 ## Current Progress
11
2 * Replaced `IDeviceContext::ExecuteCommandList()` with `IDeviceContext::ExecuteCommandLists()` method that takes
3 an array of command lists instead of one (API Version 240082)
24 * Added `IDeviceObject::SetUserData()` and `IDeviceObject::GetUserData()` methods (API Version 240081)
35
46 ## v2.4.g
8080 float f = Tex1D_F1.Load(Location.x);
8181 int2 i2 = Tex1D_I.Load(Location.x).xy;
8282 uint4 u4 = Tex1D_U.Load(Location.x);
83
84 #ifndef VULKAN // Only 4-component RW textures can be read with [] in SPIRV
85 f += Tex1D_F1[Location.x].x;
86 i2 += Tex1D_I[Location.x].xy;
87 #endif
88 u4 += Tex1D_U[Location.x];
8389 }
8490
8591 // Texture1DArray
8692 {
8793 float f = Tex1D_F_A.Load(Location.xy);
94 int2 i2 = Tex1D_I_A.Load(Location.xy);
8895 uint4 u4 = Tex1D_U_A.Load(Location.xy);
89 int2 i2 = Tex1D_I_A.Load(Location.xy);
96
97 #ifndef VULKAN // Only 4-component RW textures can be read with [] in SPIRV
98 f += Tex1D_F_A[Location.xy].x;
99 i2 += Tex1D_I_A[Location.xy].xy;
100 #endif
101 u4 += Tex1D_U_A[Location.xy];
90102 }
91103 }
92104
2424 int cbuffer_fake;
2525 int fakecbuffer;
2626
27 RWTexture2D<float/* format = r32f */>Tex2D_F1/*comment*/: /*comment*/register(u0)/*comment*/;
28 RWTexture2D<float/* format = r32f */>Tex2D_F2[2]: register(u1),Tex2D_F3: register(u2),/*cmt*/Tex2D_F4, Tex2D_F5
27 RWTexture2D<float4/* format = rgba32f */>Tex2D_F1/*comment*/: /*comment*/register(u0)/*comment*/,Tex2D_F2[2]: register(u1);
28 RWTexture2D<float/* format = r32f */>Tex2D_F3: register(u3),/*cmt*/Tex2D_F4, Tex2D_F5
2929 /*comment*/:/*comment*/
30 register(u3);
31 RWTexture2D<int2/* format = rg32i */>Tex2D_I;
32 RWTexture2D<uint4/* format = rgba16ui */>Tex2D_U;
30 register(u4);
31 RWTexture2D<int4/* format = rgba16i */>Tex2D_I;
32 RWTexture2D<uint/* format = r32ui */>Tex2D_U;
3333
3434
3535 int GlobalIntVar;Texture2D Tex2D_Test1:register(t0);Texture2D Tex2D_Test2;/*Comment* / *//* /** Comment2*/Texture2D Tex2D_Test3 /*Cmnt*/: /*comment*/register(t1)/*comment*/,/*comment*/
7070 Tex2D_F2[0].GetDimensions( fWidth, fHeight);
7171 Tex2D_I.GetDimensions (fWidth, fHeight );
7272 Tex2D_U.GetDimensions ( fWidth, fHeight );
73
74 int idx[2];
75 idx[0] = 0;
76 idx[1] = 0;
77 Tex2D_F2[idx[0]].GetDimensions( uWidth, uHeight);
7378 }
7479 }
7580
8085
8186 //Texture2D
8287 {
83 float f = Tex2D_F1.Load(Location.xy);
84 f = Tex2D_F1.Load(Tex2D_I.Load(Location.xy) + Tex2D_I.Load(Location.xy).yx);
85 int2 i2 = Tex2D_I.Load(Location.xy);
86 uint4 u4= Tex2D_U.Load(Location.xy).xyzw;
87 }
88
88 float f = Tex2D_F1.Load(Location.xy).x;
89 f += Tex2D_F1.Load(Tex2D_I.Load(Location.xy).zw + Tex2D_I.Load(Location.xy).yx).y;
90 f += Tex2D_F2[0].Load(Location.xy).x;
91 f += Tex2D_F2[1].Load(Location.xy).y;
92 f += Tex2D_F3.Load(Location.xy);
93 f += Tex2D_F4.Load(Location.xy);
94 f += Tex2D_F5.Load(Location.xy);
95
96 int2 i2 = Tex2D_I.Load(Location.xy).xy;
97 uint u = Tex2D_U.Load(Location.xy);
98
99 int idx[2];
100 idx[0] = 0;
101 idx[1] = 0;
102 f += Tex2D_F2[idx[0]].Load(Location.xy).z;
103 f += Tex2D_F2[idx[1]].Load(Location.xy).w;
104 }
105
106 {
107 float f = Tex2D_F1[Location.xy].x;
108 f += Tex2D_F1[Tex2D_I[Location.xy].xy + Tex2D_I[Location.xy].yx].x;
109
110 int idx[2];
111 idx[0] = 0;
112 idx[1] = 1;
113
114 f += Tex2D_F1[int2(idx[min(Location.x, 1)], idx[min(Location.y,1)])].y;
115
116 int2 i2 = Tex2D_I[Location.xy].xy;
117
118 f += Tex2D_F2[idx[0]][int2(idx[min(Location.x,1)], idx[min(Location.y,1)])].x;
119 f += Tex2D_F2[idx[1]][int2(idx[min(Location.y,1)], idx[min(Location.x,1)])].x;
120 f += Tex2D_F2[0][Location.xy].x;
121 f += Tex2D_F2[1][Location.xy].x;
122
123 #ifndef VULKAN // Only 4-component RW textures can be read with [] in SPIRV
124 f += Tex2D_F3[Location.xy].x;
125 f += Tex2D_F4[int2(idx[idx[min(Location.x,1)]],idx[idx[min(Location.y,1)]])].x;
126 f += Tex2D_F5[Location.xy].x;
127
128 uint u = Tex2D_U[Location.xy].x;
129 #endif
130 }
89131 }
90132
91133
94136 {
95137 //Texture2D
96138 {
97 Tex2D_F1[Location.xy] = 10.0;
98 Tex2D_F1[Tex2D_I.Load(Location.xy).xy + Tex2D_I.Load(Location.xy).xy] = 20.0;
99 Tex2D_I[Location.xy] = int2( 43, 23);
100 Tex2D_U[Location.xy] = uint4( 3,7,1,7);
139 Tex2D_F1[Location.xy] = float4(10.0, 20.0, 30.0, 40.0);
140 Tex2D_F1[Tex2D_I.Load(Location.xy).xy + Tex2D_I.Load(Location.xy).xy] = float4(20.0, 30.0, 40.0, 50.0);
141 Tex2D_F2[0][Location.xy] = float4(1.0, 2.0, 3.0, 4.0);
142 Tex2D_F2[1][Location.xy] = float4(2.0, 3.0, 5.0, 7.0);
143 Tex2D_F3[Location.xy] = 5.0;
144 Tex2D_F4[Location.xy] = 7.0;
145 Tex2D_F5[Location.xy] = 9.0;
146 Tex2D_I[Location.xy] = int4( 43, 23, 10, 20);
147 Tex2D_U[Location.xy] = 3u;
148 }
149 {
150 int2 idx[2];
151 idx[0] = int2(0,0);
152 idx[1] = int2(1,1);
153 Tex2D_F1[ idx[ min(Location.x, 1) ] ] = float4(20.0, 30.0, 50.0, 60.0);
154 Tex2D_F1[Tex2D_I[Location.xy].xy + Tex2D_I[Location.xy].zw] = 30.0;
155
156 Tex2D_F1[
157 idx[
158 Tex2D_I[
159 int2(Tex2D_I[idx[Location.x]].x, idx[Location.y].y)
160 ].x
161 ] +
162 idx[
163 Tex2D_I[
164 int2(Tex2D_I[idx[Location.y]].x, idx[Location.x].y)
165 ].x
166 ]
167 ] = Tex2D_F2[idx[0].y][int2(Tex2D_I[idx[min(Location.x,1)]].x, Tex2D_I[idx[min(Location.y,1)]].y)].xzyw;
101168 }
102169 }
103170
162229 InterlockedAdd(g_u4TestSharedVar.x, 1u);
163230 InterlockedAdd(g_i4TestSharedArr[GTid.x].x, 1, iOldVal);
164231 InterlockedAdd(g_u4TestSharedArr[Gid.x].x, 1u, uOldVal);
232 InterlockedAdd(Tex2D_U[Gid.xy], 1u, uOldVal);
165233
166234 InterlockedAnd(g_i4TestSharedVar.x, 1);
167235 InterlockedAnd(g_u4TestSharedVar.x, 1u);
168236 InterlockedAnd(g_i4TestSharedArr[GTid.x].x, 1, iOldVal);
169237 InterlockedAnd(g_u4TestSharedArr[Gid.x].x, 1u, uOldVal);
238 InterlockedAnd(Tex2D_U[Gid.xy], 1u, uOldVal);
170239
171240 InterlockedOr(g_i4TestSharedVar.x, 1);
172241 InterlockedOr(g_u4TestSharedVar.x, 1u);
173242 InterlockedOr(g_i4TestSharedArr[GTid.x].x, 1, iOldVal);
174243 InterlockedOr(g_u4TestSharedArr[Gid.x].x, 1u, uOldVal);
244 InterlockedOr(Tex2D_U[Gid.xy], 1u, uOldVal);
175245
176246 InterlockedXor(g_i4TestSharedVar.x, 1);
177247 InterlockedXor(g_u4TestSharedVar.x, 1u);
178248 InterlockedXor(g_i4TestSharedArr[GTid.x].x, 1, iOldVal);
179249 InterlockedXor(g_u4TestSharedArr[Gid.x].x, 1u, uOldVal);
250 InterlockedXor(Tex2D_U[Gid.xy], 1u, uOldVal);
180251
181252 InterlockedMax(g_i4TestSharedVar.x, 1);
182253 InterlockedMax(g_u4TestSharedVar.x, 1u);
183254 InterlockedMax(g_i4TestSharedArr[GTid.x].x, 1, iOldVal);
184255 InterlockedMax(g_u4TestSharedArr[Gid.x].x, 1u, uOldVal);
256 InterlockedMax(Tex2D_U[Gid.xy], 1u, uOldVal);
185257
186258 InterlockedMin(g_i4TestSharedVar.x, 1);
187259 InterlockedMin(g_u4TestSharedVar.x, 1u);
188260 InterlockedMin(g_i4TestSharedArr[GTid.x].x, 1, iOldVal);
189261 InterlockedMin(g_u4TestSharedArr[Gid.x].x, 1u, uOldVal);
262 InterlockedMin(Tex2D_U[Gid.xy], 1u, uOldVal);
263
190264
191265 // There is actually no InterlockedExchange() with 2 arguments
192266 //InterlockedExchange(g_i4TestSharedVar.x, 1);
193267 //InterlockedExchange(g_u4TestSharedVar.x, 1u);
194268 InterlockedExchange(g_i4TestSharedArr[GTid.x].x, 1, iOldVal);
195269 InterlockedExchange(g_u4TestSharedArr[Gid.x].x, 1u, uOldVal);
270 InterlockedExchange(Tex2D_U[Gid.xy], 1u, uOldVal);
196271
197272 InterlockedCompareStore(g_i4TestSharedVar.x, 1, 10);
198273 InterlockedCompareStore(g_u4TestSharedVar.x, 1u, 10u);
199274 InterlockedCompareExchange(g_i4TestSharedArr[GTid.x].x, 1, 10, iOldVal);
200275 InterlockedCompareExchange(g_u4TestSharedArr[Gid.x].x, 1u, 10u, uOldVal);
276 InterlockedCompareExchange(Tex2D_U[Gid.xy], 1u, 10u, uOldVal);
201277
202278 //uint2 ui2Dim;
203279 //g_tex2DTestUAV.GetDimensions(ui2Dim.x, ui2Dim.y);
6565 float f = Tex2D_F_A.Load(Location.xyz);
6666 uint4 u4 = Tex2D_U_A.Load(Location.xyz);
6767 int2 i2 = Tex2D_I_A.Load(Location.xyz);
68
69 u4 += Tex2D_U_A[Location.xyz];
70 #ifndef VULKAN // Only 4-component RW textures can be read with [] in SPIRV
71 f += Tex2D_F_A[Location.xyz].x;
72 i2 += Tex2D_I_A[Location.xyz].xy;
73 #endif
6874 }
6975
7076 //Texture3D
7278 float4 f4 = Tex3D_F.Load(Location.xyz).xyzw;
7379 uint2 u2 = Tex3D_U.Load(Location.xyz).xy;
7480 int i = Tex3D_I.Load(Location.xyz);
81
82 f4 += Tex3D_F[Location.xyz].xyzw;
83 #ifndef VULKAN // Only 4-component RW textures can be read with [] in SPIRV
84 u2 += Tex3D_U[Location.xyz].xy;
85 i += Tex3D_I[Location.xyz].x;
86 #endif
7587 }
7688 }
7789
9090 f4Position = Pos[VertId];
9191 }
9292
93 float4 PSMain(in float4 in_f4Color : COLOR,
93 float4 PSMain(in float4 f4Color : COLOR, // Name must match VS output
9494 in float4 f4Position : SV_Position) : SV_Target
9595 {
96 return in_f4Color * VerifyResources();
96 return f4Color * VerifyResources();
9797 }
5959 f4Position = Pos[VertId];
6060 }
6161
62 float4 PSMain(in float4 in_f4Color : COLOR,
62 float4 PSMain(in float4 f4Color : COLOR, // Name must match VS output
6363 in float4 f4Position : SV_Position) : SV_Target
6464 {
65 return in_f4Color * VerifyResources();
65 return f4Color * VerifyResources();
6666 }
6666 f4Position = Pos[VertId];
6767 }
6868
69 float4 PSMain(in float4 in_f4Color : COLOR,
69 float4 PSMain(in float4 f4Color : COLOR, // Name must match VS output
7070 in float4 f4Position : SV_Position) : SV_Target
7171 {
72 return in_f4Color * VerifyResources();
72 return f4Color * VerifyResources();
7373 }
4444 #endif
4545
4646 AllCorrect *= CheckValue(g_RWBuffArr_Mut[0][1], BuffArr_Mut_Ref0);
47 g_RWBuffArr_Mut[0][0] = f4Data;
48
49 #if (MUTABLE_BUFF_ARRAY_SIZE == 3)
4750 AllCorrect *= CheckValue(g_RWBuffArr_Mut[1][2], BuffArr_Mut_Ref1);
48
49 g_RWBuffArr_Mut[0][0] = f4Data;
50 g_RWBuffArr_Mut[1][0] = f4Data;
51 #if (MUTABLE_BUFF_ARRAY_SIZE == 3)
5251 AllCorrect *= CheckValue(g_RWBuffArr_Mut[2][2], BuffArr_Mut_Ref2);
5352
53 g_RWBuffArr_Mut[1][0] = f4Data;
5454 g_RWBuffArr_Mut[2][0] = f4Data;
5555 #endif
5656
0 layout(std140, binding = 0) writeonly buffer g_RWBuff_Static
0 layout(std140, binding = 0) buffer g_RWBuff_Static
11 {
22 vec4 data[4];
33 }g_StorageBuff_Static;
44
5 layout(std140, binding = 1) writeonly buffer g_RWBuff_Mut
5 layout(std140, binding = 1) buffer g_RWBuff_Mut
66 {
77 vec4 data[4];
88 }g_StorageBuff_Mut;
99
10 layout(std140, binding = 2) writeonly buffer g_RWBuff_Dyn
10 layout(std140, binding = 2) buffer g_RWBuff_Dyn
1111 {
1212 vec4 data[4];
1313 }g_StorageBuff_Dyn;
1414
1515
16 layout(std140, binding = 3) writeonly buffer g_RWBuffArr_Static
16 layout(std140, binding = 3) buffer g_RWBuffArr_Static
1717 {
1818 vec4 data[4];
1919 }g_StorageBuffArr_Static[STATIC_BUFF_ARRAY_SIZE]; // 4 or 1 in OpenGL
2020
21 layout(std140, binding = 7) writeonly buffer g_RWBuffArr_Mut
21 layout(std140, binding = 7) buffer g_RWBuffArr_Mut
2222 {
2323 vec4 data[4];
2424 }g_StorageBuffArr_Mut[MUTABLE_BUFF_ARRAY_SIZE]; // 3 or 2 in OpenGL
2525
26 layout(std140, binding = 10) writeonly buffer g_RWBuffArr_Dyn
26 layout(std140, binding = 10) buffer g_RWBuffArr_Dyn
2727 {
2828 vec4 data[4];
2929 }g_StorageBuffArr_Dyn[DYNAMIC_BUFF_ARRAY_SIZE]; // 2
6868 #endif
6969
7070 AllCorrect *= CheckValue(g_StorageBuffArr_Mut[0].data[1], BuffArr_Mut_Ref0);
71 AllCorrect *= CheckValue(g_StorageBuffArr_Mut[1].data[2], BuffArr_Mut_Ref1);
7271
7372 g_StorageBuffArr_Mut[0].data[0] = Data;
74 g_StorageBuffArr_Mut[1].data[0] = Data;
7573 #if (MUTABLE_BUFF_ARRAY_SIZE == 3)
74 AllCorrect *= CheckValue(g_StorageBuffArr_Mut[1].data[2], BuffArr_Mut_Ref1);
7675 AllCorrect *= CheckValue(g_StorageBuffArr_Mut[2].data[1], BuffArr_Mut_Ref2);
7776
77 g_StorageBuffArr_Mut[1].data[0] = Data;
7878 g_StorageBuffArr_Mut[2].data[0] = Data;
7979 #endif
8080
4949 #endif
5050
5151 AllCorrect *= CheckValue(g_RWBuffArr_Mut[0][1].data, BuffArr_Mut_Ref0);
52 AllCorrect *= CheckValue(g_RWBuffArr_Mut[1][2].data, BuffArr_Mut_Ref1);
5352
5453 g_RWBuffArr_Mut[0][0].data = f4Data;
55 g_RWBuffArr_Mut[1][0].data = f4Data;
5654 #if (MUTABLE_BUFF_ARRAY_SIZE == 3)
55 AllCorrect *= CheckValue(g_RWBuffArr_Mut[1][2].data, BuffArr_Mut_Ref1);
5756 AllCorrect *= CheckValue(g_RWBuffArr_Mut[2][1].data, BuffArr_Mut_Ref2);
5857
58 g_RWBuffArr_Mut[1][0].data = f4Data;
5959 g_RWBuffArr_Mut[2][0].data = f4Data;
6060 #endif
6161
6464
6565 g_RWBuffArr_Dyn[0][0].data = f4Data;
6666 g_RWBuffArr_Dyn[1][0].data = f4Data;
67
68 return AllCorrect;
6769 }
6870
6971 RWTexture2D</*format=rgba8*/ float4> g_tex2DUAV;
0 RWTexture2D<float4 /*format=rgba32f*/> g_RWTex2D_Static;
1 RWTexture2D<float4 /*format=rgba32f*/> g_RWTex2D_Mut;
2 RWTexture2D<float4 /*format=rgba32f*/> g_RWTex2D_Dyn;
0 RWTexture2D<unorm float4 /*format=rgba8*/> g_RWTex2D_Static;
1 RWTexture2D<unorm float4 /*format=rgba8*/> g_RWTex2D_Mut;
2 RWTexture2D<unorm float4 /*format=rgba8*/> g_RWTex2D_Dyn;
33
4 RWTexture2D<float4 /*format=rgba32f*/> g_RWTex2DArr_Static[STATIC_TEX_ARRAY_SIZE]; // 2
5 RWTexture2D<float4 /*format=rgba32f*/> g_RWTex2DArr_Mut [MUTABLE_TEX_ARRAY_SIZE]; // 4 or 2 in D3D11
6 RWTexture2D<float4 /*format=rgba32f*/> g_RWTex2DArr_Dyn [DYNAMIC_TEX_ARRAY_SIZE]; // 3 or 1 in D3D11
4 RWTexture2D<unorm float4 /*format=rgba8*/> g_RWTex2DArr_Static[STATIC_TEX_ARRAY_SIZE]; // 2
5 RWTexture2D<unorm float4 /*format=rgba8*/> g_RWTex2DArr_Mut [MUTABLE_TEX_ARRAY_SIZE]; // 4 or 2 in D3D11
6 RWTexture2D<unorm float4 /*format=rgba8*/> g_RWTex2DArr_Dyn [DYNAMIC_TEX_ARRAY_SIZE]; // 3 or 1 in D3D11
77
88 float4 CheckValue(float4 Val, float4 Expected)
99 {
3535 g_RWTex2DArr_Static[1][int2(0,0)] = f4Color;
3636
3737 AllCorrect *= CheckValue(g_RWTex2DArr_Mut[0][int2(32, 21)], Tex2DArr_Mut_Ref0);
38 g_RWTex2DArr_Mut[0][int2(0,0)] = f4Color;
39
40 #if (MUTABLE_TEX_ARRAY_SIZE == 4)
3841 AllCorrect *= CheckValue(g_RWTex2DArr_Mut[1][int2(31, 24)], Tex2DArr_Mut_Ref1);
39
40 g_RWTex2DArr_Mut[0][int2(0,0)] = f4Color;
41 g_RWTex2DArr_Mut[1][int2(0,0)] = f4Color;
42 #if (MUTABLE_TEX_ARRAY_SIZE == 4)
4342 AllCorrect *= CheckValue(g_RWTex2DArr_Mut[2][int2(42, 56)], Tex2DArr_Mut_Ref2);
4443 AllCorrect *= CheckValue(g_RWTex2DArr_Mut[3][int2(45, 54)], Tex2DArr_Mut_Ref3);
4544
45 g_RWTex2DArr_Mut[1][int2(0,0)] = f4Color;
4646 g_RWTex2DArr_Mut[2][int2(0,0)] = f4Color;
4747 g_RWTex2DArr_Mut[3][int2(0,0)] = f4Color;
4848 #endif
4949
5050 AllCorrect *= CheckValue(g_RWTex2DArr_Dyn[0][int2(67, 54)], Tex2DArr_Dyn_Ref0);
51 g_RWTex2DArr_Dyn[0][int2(0,0)] = f4Color;
52
53 #if (DYNAMIC_TEX_ARRAY_SIZE == 3)
5154 AllCorrect *= CheckValue(g_RWTex2DArr_Dyn[1][int2(73, 58)], Tex2DArr_Dyn_Ref1);
5255 AllCorrect *= CheckValue(g_RWTex2DArr_Dyn[2][int2(78, 92)], Tex2DArr_Dyn_Ref2);
5356
54 g_RWTex2DArr_Dyn[0][int2(0,0)] = f4Color;
55 #if (DYNAMIC_TEX_ARRAY_SIZE == 3)
5657 g_RWTex2DArr_Dyn[1][int2(0,0)] = f4Color;
5758 g_RWTex2DArr_Dyn[2][int2(0,0)] = f4Color;
5859 #endif
6060 f4Position = Pos[VertId];
6161 }
6262
63 float4 PSMain(in float4 in_f4Color : COLOR,
63 float4 PSMain(in float4 f4Color : COLOR, // Name must match VS output
6464 in float4 f4Position : SV_Position) : SV_Target
6565 {
66 return in_f4Color * VerifyResources();
66 return f4Color * VerifyResources();
6767 }
5050 public:
5151 struct CreateInfo
5252 {
53 RENDER_DEVICE_TYPE deviceType = RENDER_DEVICE_TYPE_UNDEFINED;
54 ADAPTER_TYPE AdapterType = ADAPTER_TYPE_UNKNOWN;
55 Uint32 AdapterId = DEFAULT_ADAPTER_ID;
56
57 bool ForceNonSeparablePrograms = false;
53 RENDER_DEVICE_TYPE deviceType = RENDER_DEVICE_TYPE_UNDEFINED;
54 ADAPTER_TYPE AdapterType = ADAPTER_TYPE_UNKNOWN;
55 Uint32 AdapterId = DEFAULT_ADAPTER_ID;
56 Uint32 NumDeferredContexts = 4;
57 bool ForceNonSeparablePrograms = false;
5858 };
5959 TestingEnvironment(const CreateInfo& CI, const SwapChainDesc& SCDesc);
6060
9393 };
9494
9595 IRenderDevice* GetDevice() { return m_pDevice; }
96 IDeviceContext* GetDeviceContext() { return m_pDeviceContext; }
96 IDeviceContext* GetDeviceContext(size_t ctx = 0) { return m_pDeviceContexts[ctx]; }
9797 ISwapChain* GetSwapChain() { return m_pSwapChain; }
98 size_t GetNumDeferredContexts() const { return m_pDeviceContexts.size() - 1; }
9899
99100 static TestingEnvironment* GetInstance() { return m_pTheEnvironment; }
100101
105106 void SetDefaultCompiler(SHADER_COMPILER compiler);
106107 SHADER_COMPILER GetDefaultCompiler(SHADER_SOURCE_LANGUAGE lang) const;
107108
109 ADAPTER_TYPE GetAdapterType() const { return m_AdapterType; }
110
108111 protected:
109112 NativeWindow CreateNativeWindow();
110113
114117 const char* File,
115118 int Line);
116119
117 static Uint32 FindAdapater(const std::vector<GraphicsAdapterInfo>& Adapters,
118 ADAPTER_TYPE AdapterType,
119 Uint32 AdapterId);
120 Uint32 FindAdapater(const std::vector<GraphicsAdapterInfo>& Adapters,
121 ADAPTER_TYPE AdapterType,
122 Uint32 AdapterId);
120123
121124 const RENDER_DEVICE_TYPE m_DeviceType;
125
126 ADAPTER_TYPE m_AdapterType = ADAPTER_TYPE_UNKNOWN;
122127
123128 // Any platform-specific data (e.g. window handle) that should
124129 // be cleaned-up when the testing environment object is destroyed.
130135
131136 static TestingEnvironment* m_pTheEnvironment;
132137
133 RefCntAutoPtr<IRenderDevice> m_pDevice;
134 RefCntAutoPtr<IDeviceContext> m_pDeviceContext;
135 RefCntAutoPtr<ISwapChain> m_pSwapChain;
136 SHADER_COMPILER m_ShaderCompiler = SHADER_COMPILER_DEFAULT;
138 RefCntAutoPtr<IRenderDevice> m_pDevice;
139 std::vector<RefCntAutoPtr<IDeviceContext>> m_pDeviceContexts;
140 RefCntAutoPtr<ISwapChain> m_pSwapChain;
141 SHADER_COMPILER m_ShaderCompiler = SHADER_COMPILER_DEFAULT;
137142
138143 static std::atomic_int m_NumAllowedErrors;
139144 };
4848 TestingEnvironment{CI, SCDesc}
4949 {
5050 RefCntAutoPtr<IRenderDeviceD3D11> pRenderDeviceD3D11{m_pDevice, IID_RenderDeviceD3D11};
51 RefCntAutoPtr<IDeviceContextD3D11> pContextD3D11{m_pDeviceContext, IID_DeviceContextD3D11};
51 RefCntAutoPtr<IDeviceContextD3D11> pContextD3D11{GetDeviceContext(), IID_DeviceContextD3D11};
5252
5353 m_pd3d11Device = pRenderDeviceD3D11->GetD3D11Device();
5454 m_pd3d11Context = pContextD3D11->GetD3D11DeviceContext();
8181
8282 if (m_pSwapChain == nullptr)
8383 {
84 CreateTestingSwapChainD3D11(m_pDevice, m_pDeviceContext, SCDesc, &m_pSwapChain);
84 CreateTestingSwapChainD3D11(m_pDevice, GetDeviceContext(), SCDesc, &m_pSwapChain);
8585 }
8686 }
8787
5959
6060 if (m_pSwapChain == nullptr)
6161 {
62 CreateTestingSwapChainD3D12(m_pDevice, m_pDeviceContext, SCDesc, &m_pSwapChain);
62 CreateTestingSwapChainD3D12(m_pDevice, GetDeviceContext(), SCDesc, &m_pSwapChain);
6363 }
6464 }
6565
9393
9494 void TestingEnvironmentD3D12::ExecuteCommandList(ID3D12CommandList* pCmdList, bool WaitForIdle)
9595 {
96 auto pContextD3D12 = m_pDeviceContext.Cast<IDeviceContextD3D12>(IID_DeviceContextD3D12);
96 RefCntAutoPtr<IDeviceContextD3D12> pContextD3D12{GetDeviceContext(), IID_DeviceContextD3D12};
9797
9898 auto* pQeueD3D12 = pContextD3D12->LockCommandQueue();
9999 auto* pd3d12Queue = pQeueD3D12->GetD3D12CommandQueue();
2424 * of the possibility of such damages.
2525 */
2626
27 #include <thread>
28 #include <array>
29
2730 #include "TestingEnvironment.hpp"
2831 #include "TestingSwapChainBase.hpp"
2932 #include "BasicMath.hpp"
15311534 Present();
15321535 }
15331536
1537 TEST_F(DrawCommandTest, DeferredContexts)
1538 {
1539 auto* pEnv = TestingEnvironment::GetInstance();
1540 if (pEnv->GetNumDeferredContexts() == 0)
1541 {
1542 GTEST_SKIP() << "Deferred contexts are not supported by this device";
1543 }
1544 VERIFY(pEnv->GetNumDeferredContexts() >= 2, "At least two deferred contexts are expected");
1545
1546 auto* pSwapChain = pEnv->GetSwapChain();
1547 auto* pImmediateCtx = pEnv->GetDeviceContext();
1548
1549 Uint32 Indices[] = {0, 1, 2, 3, 4, 5};
1550 auto pVB = CreateVertexBuffer(Vert, sizeof(Vert));
1551 auto pIB = CreateIndexBuffer(Indices, _countof(Indices));
1552
1553 StateTransitionDesc Barriers[] = //
1554 {
1555 {pVB, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_VERTEX_BUFFER, true},
1556 {pIB, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_INDEX_BUFFER, true} //
1557 };
1558 pImmediateCtx->TransitionResourceStates(_countof(Barriers), Barriers);
1559
1560 ITextureView* pRTVs[] = {pSwapChain->GetCurrentBackBufferRTV()};
1561 const float ClearColor[] = {0.f, 0.f, 0.f, 0.0f};
1562 pImmediateCtx->SetRenderTargets(1, pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
1563 pImmediateCtx->ClearRenderTarget(pRTVs[0], ClearColor, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
1564
1565 constexpr Uint32 NumThreads = 2;
1566 std::array<std::thread, NumThreads> WorkerThreads;
1567 std::array<RefCntAutoPtr<ICommandList>, NumThreads> CmdLists;
1568 std::array<ICommandList*, NumThreads> CmdListPtrs;
1569 for (Uint32 i = 0; i < NumThreads; ++i)
1570 {
1571 WorkerThreads[i] = std::thread(
1572 [&](Uint32 thread_id) //
1573 {
1574 auto* pCtx = pEnv->GetDeviceContext(thread_id + 1);
1575
1576 pCtx->SetRenderTargets(1, pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
1577
1578 IBuffer* pVBs[] = {pVB};
1579 Uint32 Offsets[] = {0};
1580 pCtx->SetVertexBuffers(0, 1, pVBs, Offsets, RESOURCE_STATE_TRANSITION_MODE_VERIFY, SET_VERTEX_BUFFERS_FLAG_RESET);
1581 pCtx->SetIndexBuffer(pIB, 0, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
1582
1583 pCtx->SetPipelineState(sm_pDrawPSO);
1584
1585 DrawIndexedAttribs drawAttrs{3, VT_UINT32, DRAW_FLAG_VERIFY_ALL};
1586 drawAttrs.FirstIndexLocation = 3 * thread_id;
1587 pCtx->DrawIndexed(drawAttrs);
1588
1589 pCtx->FinishCommandList(&CmdLists[thread_id]);
1590 CmdListPtrs[thread_id] = CmdLists[thread_id];
1591 },
1592 i);
1593 }
1594
1595 for (auto& t : WorkerThreads)
1596 t.join();
1597
1598 pImmediateCtx->ExecuteCommandLists(NumThreads, CmdListPtrs.data());
1599
1600 for (size_t i = 0; i < NumThreads; ++i)
1601 pEnv->GetDeviceContext(i + 1)->FinishFrame();
1602
1603 Present();
1604 }
1605
1606
15341607 void DrawCommandTest::TestDynamicBufferUpdates(IShader* pVS,
15351608 IShader* pPS,
15361609 IBuffer* pDynamicCB0,
4848
4949 if (m_pSwapChain == nullptr)
5050 {
51 CreateTestingSwapChainGL(m_pDevice, m_pDeviceContext, SCDesc, &m_pSwapChain);
51 CreateTestingSwapChainGL(m_pDevice, GetDeviceContext(), SCDesc, &m_pSwapChain);
5252 }
5353
5454 glGenVertexArrays(1, &m_DummyVAO);
3737 #include "InlineShaders/RayTracingTestHLSL.h"
3838 #include "RayTracingTestConstants.hpp"
3939
40 #include "Vulkan/TestingEnvironmentVk.hpp"
41
4240 namespace Diligent
4341 {
4442
103103 {
104104 if (Adapters[i].Type == AdapterType)
105105 {
106 AdapterId = i;
106 AdapterId = i;
107 m_AdapterType = AdapterType;
107108 break;
108109 }
109110 }
193194
194195 CreateInfo.AdapterId = FindAdapater(Adapters, CI.AdapterType, CI.AdapterId);
195196
197 NumDeferredCtx = CI.NumDeferredContexts;
196198 CreateInfo.NumDeferredContexts = NumDeferredCtx;
197199 ppContexts.resize(1 + NumDeferredCtx);
198200 pFactoryD3D11->CreateDeviceAndContextsD3D11(CreateInfo, &m_pDevice, ppContexts.data());
253255 CreateInfo.CPUDescriptorHeapAllocationSize[3] = 16; // D3D12_DESCRIPTOR_HEAP_TYPE_DSV
254256 CreateInfo.DynamicDescriptorAllocationChunkSize[0] = 8; // D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV
255257 CreateInfo.DynamicDescriptorAllocationChunkSize[1] = 8; // D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER
258
259 NumDeferredCtx = CI.NumDeferredContexts;
260 CreateInfo.NumDeferredContexts = NumDeferredCtx;
256261 ppContexts.resize(1 + NumDeferredCtx);
257
258 CreateInfo.NumDeferredContexts = NumDeferredCtx;
259262 pFactoryD3D12->CreateDeviceAndContextsD3D12(CreateInfo, &m_pDevice, ppContexts.data());
260263 }
261264 break;
284287 CreateInfo.CreateDebugContext = true;
285288 CreateInfo.Features = DeviceFeatures{DEVICE_FEATURE_STATE_OPTIONAL};
286289 CreateInfo.ForceNonSeparablePrograms = CI.ForceNonSeparablePrograms;
287 if (NumDeferredCtx != 0)
288 {
289 LOG_ERROR_MESSAGE("Deferred contexts are not supported in OpenGL mode");
290 NumDeferredCtx = 0;
291 }
290 NumDeferredCtx = 0;
292291 ppContexts.resize(1 + NumDeferredCtx);
293292 RefCntAutoPtr<ISwapChain> pSwapChain; // We will use testing swap chain instead
294293 pFactoryOpenGL->CreateDeviceAndSwapChainGL(
320319 //CreateInfo.HostVisibleMemoryReserveSize = 48 << 20;
321320 CreateInfo.Features = DeviceFeatures{DEVICE_FEATURE_STATE_OPTIONAL};
322321
322 NumDeferredCtx = CI.NumDeferredContexts;
323323 CreateInfo.NumDeferredContexts = NumDeferredCtx;
324324 ppContexts.resize(1 + NumDeferredCtx);
325325 auto* pFactoryVk = GetEngineFactoryVk();
334334 EngineMtlCreateInfo MtlAttribs;
335335
336336 MtlAttribs.DebugMessageCallback = MessageCallback;
337 NumDeferredCtx = CI.NumDeferredContexts;
337338 MtlAttribs.NumDeferredContexts = NumDeferredCtx;
338339 ppContexts.resize(1 + NumDeferredCtx);
339340 auto* pFactoryMtl = GetEngineFactoryMtl();
346347 LOG_ERROR_AND_THROW("Unknown device type");
347348 break;
348349 }
349 m_pDeviceContext.Attach(ppContexts[0]);
350 m_pDeviceContexts.resize(ppContexts.size());
351 for (size_t i = 0; i < ppContexts.size(); ++i)
352 m_pDeviceContexts[i].Attach(ppContexts[i]);
350353
351354 const auto& AdapterInfo = m_pDevice->GetDeviceCaps().AdapterInfo;
352355 std::string AdapterInfoStr;
391394
392395 TestingEnvironment::~TestingEnvironment()
393396 {
394 m_pDeviceContext->Flush();
395 m_pDeviceContext->FinishFrame();
397 auto* pCtx = GetDeviceContext();
398 pCtx->Flush();
399 pCtx->FinishFrame();
396400 }
397401
398402 // Override this to define how to set up the environment.
410414 // It is necessary to call Flush() to force the driver to release resources.
411415 // Without flushing the command buffer, the memory may not be released until sometimes
412416 // later causing out-of-memory error.
413 m_pDeviceContext->Flush();
414 m_pDeviceContext->FinishFrame();
417 auto* pCtx = GetDeviceContext();
418 pCtx->Flush();
419 pCtx->FinishFrame();
415420 m_pDevice->ReleaseStaleResources();
416421 }
417422
418423 void TestingEnvironment::Reset()
419424 {
420 m_pDeviceContext->Flush();
421 m_pDeviceContext->FinishFrame();
425 auto* pCtx = GetDeviceContext();
426 pCtx->Flush();
427 pCtx->FinishFrame();
422428 m_pDevice->IdleGPU();
423429 m_pDevice->ReleaseStaleResources();
424 m_pDeviceContext->InvalidateState();
430 pCtx->InvalidateState();
425431 m_NumAllowedErrors = 0;
426432 }
427433
6262
6363 volkLoadInstance(pRenderDeviceVk->GetVkInstance());
6464
65 RefCntAutoPtr<IDeviceContextVk> pContextVk{m_pDeviceContext, IID_DeviceContextVk};
65 RefCntAutoPtr<IDeviceContextVk> pContextVk{GetDeviceContext(), IID_DeviceContextVk};
6666
6767 auto* pQeueVk = pContextVk->LockCommandQueue();
6868 auto QueueFamilyIndex = pQeueVk->GetQueueFamilyIndex();
382382
383383 void TestingEnvironmentVk::SubmitCommandBuffer(VkCommandBuffer vkCmdBuffer, bool WaitForIdle)
384384 {
385 RefCntAutoPtr<IDeviceContextVk> pContextVk{m_pDeviceContext, IID_DeviceContextVk};
385 RefCntAutoPtr<IDeviceContextVk> pContextVk{GetDeviceContext(), IID_DeviceContextVk};
386386
387387 auto* pQeueVk = pContextVk->LockCommandQueue();
388388 auto vkQueue = pQeueVk->GetVkQueue();
3232 Uint64 FenceVal = ICommandQueueD3D12_GetNextFenceValue(pQueue);
3333 (void)FenceVal;
3434
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, (ID3D12GraphicsCommandList*)NULL);
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, 1, (ID3D12CommandList* const*)NULL);
3636
3737 ID3D12CommandQueue* pd3d12Queue = ICommandQueueD3D12_GetD3D12CommandQueue(pQueue);
3838 (void)pd3d12Queue;
3232 Uint64 FenceVal = ICommandQueueD3D12_GetNextFenceValue(pQueue);
3333 (void)FenceVal;
3434
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, (ID3D12GraphicsCommandList*)NULL);
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, 1, (ID3D12CommandList* const*)NULL);
3636
3737 ID3D12CommandQueue* pd3d12Queue = ICommandQueueD3D12_GetD3D12CommandQueue(pQueue);
3838 (void)pd3d12Queue;
3232 Uint64 FenceVal = ICommandQueueD3D12_GetNextFenceValue(pQueue);
3333 (void)FenceVal;
3434
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, (ID3D12GraphicsCommandList*)NULL);
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, 1, (ID3D12CommandList* const*)NULL);
3636
3737 ID3D12CommandQueue* pd3d12Queue = ICommandQueueD3D12_GetD3D12CommandQueue(pQueue);
3838 (void)pd3d12Queue;
3232 Uint64 FenceVal = ICommandQueueD3D12_GetNextFenceValue(pQueue);
3333 (void)FenceVal;
3434
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, (ID3D12GraphicsCommandList*)NULL);
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, 1, (ID3D12CommandList* const*)NULL);
3636
3737 ID3D12CommandQueue* pd3d12Queue = ICommandQueueD3D12_GetD3D12CommandQueue(pQueue);
3838 (void)pd3d12Queue;
3232 Uint64 FenceVal = ICommandQueueD3D12_GetNextFenceValue(pQueue);
3333 (void)FenceVal;
3434
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, (ID3D12GraphicsCommandList*)NULL);
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, 1, (ID3D12CommandList* const*)NULL);
3636
3737 ID3D12CommandQueue* pd3d12Queue = ICommandQueueD3D12_GetD3D12CommandQueue(pQueue);
3838 (void)pd3d12Queue;
3232 Uint64 FenceVal = ICommandQueueD3D12_GetNextFenceValue(pQueue);
3333 (void)FenceVal;
3434
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, (ID3D12GraphicsCommandList*)NULL);
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, 1, (ID3D12CommandList* const*)NULL);
3636
3737 ID3D12CommandQueue* pd3d12Queue = ICommandQueueD3D12_GetD3D12CommandQueue(pQueue);
3838 (void)pd3d12Queue;
3232 Uint64 FenceVal = ICommandQueueD3D12_GetNextFenceValue(pQueue);
3333 (void)FenceVal;
3434
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, (ID3D12GraphicsCommandList*)NULL);
35 FenceVal = ICommandQueueD3D12_Submit(pQueue, 1, (ID3D12CommandList* const*)NULL);
3636
3737 ID3D12CommandQueue* pd3d12Queue = ICommandQueueD3D12_GetD3D12CommandQueue(pQueue);
3838 (void)pd3d12Queue;