diff --git a/Inc/SpriteBatch.h b/Inc/SpriteBatch.h index 41556cb3..6659a124 100644 --- a/Inc/SpriteBatch.h +++ b/Inc/SpriteBatch.h @@ -91,7 +91,8 @@ namespace DirectX samplerDescriptor{}, customRootSignature(nullptr), customVertexShader{}, - customPixelShader{} + customPixelShader{}, + customCBV(false) { if (isamplerDescriptor) this->samplerDescriptor = *isamplerDescriptor; @@ -105,6 +106,7 @@ namespace DirectX ID3D12RootSignature* customRootSignature; D3D12_SHADER_BYTECODE customVertexShader; D3D12_SHADER_BYTECODE customPixelShader; + bool customCBV; private: static const D3D12_BLEND_DESC s_DefaultBlendDesc; @@ -133,11 +135,30 @@ namespace DirectX _In_ ID3D12GraphicsCommandList* commandList, SpriteSortMode sortMode = SpriteSortMode_Deferred, FXMMATRIX transformMatrix = MatrixIdentity); + // Begin using a static sampler. + + DIRECTX_TOOLKIT_API void XM_CALLCONV Begin( + _In_ ID3D12GraphicsCommandList* commandList, + D3D12_GPU_DESCRIPTOR_HANDLE sampler, + SpriteSortMode sortMode = SpriteSortMode_Deferred, + FXMMATRIX transformMatrix = MatrixIdentity); + // Begin with a heap-based sampler. + + DIRECTX_TOOLKIT_API void XM_CALLCONV Begin( + _In_ ID3D12GraphicsCommandList* commandList, + std::function setCustomCallback, + SpriteSortMode sortMode = SpriteSortMode_Deferred, + FXMMATRIX transformMatrix = MatrixIdentity); + // Begin with a static sampler and custom callback. + DIRECTX_TOOLKIT_API void XM_CALLCONV Begin( _In_ ID3D12GraphicsCommandList* commandList, D3D12_GPU_DESCRIPTOR_HANDLE sampler, + std::function setCustomCallback, SpriteSortMode sortMode = SpriteSortMode_Deferred, FXMMATRIX transformMatrix = MatrixIdentity); + // Begin with a heap-based sampler and custom callback. + DIRECTX_TOOLKIT_API void __cdecl End(); // Draw overloads specifying position, origin and scale as XMFLOAT2. @@ -192,6 +213,9 @@ namespace DirectX // Set viewport for sprite transformation DIRECTX_TOOLKIT_API void __cdecl SetViewport(const D3D12_VIEWPORT& viewPort); + // Gets transform matrix based on viewport and rotation mode + DIRECTX_TOOLKIT_API void GetViewportTransform(XMMATRIX& transformMatrix) const; + private: // Private implementation. struct Impl; diff --git a/Src/SpriteBatch.cpp b/Src/SpriteBatch.cpp index 39b54126..bcb63d4b 100644 --- a/Src/SpriteBatch.cpp +++ b/Src/SpriteBatch.cpp @@ -123,6 +123,9 @@ XM_ALIGNED_STRUCT(16) SpriteBatch::Impl : public AlignedNew bool mSetViewport; D3D12_VIEWPORT mViewPort; D3D12_GPU_DESCRIPTOR_HANDLE mSampler; + std::function mCustomCallback; + + XMMATRIX GetViewportTransform(_In_ DXGI_MODE_ROTATION rotation); private: // Implementation helper methods. @@ -143,8 +146,6 @@ XM_ALIGNED_STRUCT(16) SpriteBatch::Impl : public AlignedNew FXMVECTOR textureSize, FXMVECTOR inverseTextureSize) noexcept; - XMMATRIX GetViewportTransform(_In_ DXGI_MODE_ROTATION rotation); - // Constants. static constexpr size_t MaxBatchSize = 2048; static constexpr size_t MinBatchSize = 128; @@ -175,6 +176,8 @@ XM_ALIGNED_STRUCT(16) SpriteBatch::Impl : public AlignedNew // mSpriteQueue array, and we take care to keep them in order when sorting is disabled. std::vector mSortedSprites; + // Custom flags. + bool mCustomCBV; // Mode settings from the last Begin call. bool mInBeginEndPair; @@ -438,6 +441,7 @@ SpriteBatch::Impl::Impl(ID3D12Device* device, mSampler{}, mSpriteQueueCount(0), mSpriteQueueArraySize(0), + mCustomCBV(false), mInBeginEndPair(false), mSortMode(SpriteSortMode_Deferred), mTransformMatrix(MatrixIdentity), @@ -475,6 +479,7 @@ SpriteBatch::Impl::Impl(ID3D12Device* device, if (psoDesc.customRootSignature) { mRootSignature = psoDesc.customRootSignature; + mCustomCBV = psoDesc.customCBV; } else { @@ -558,8 +563,10 @@ void SpriteBatch::Impl::End() // Break circular reference chains, in case the state lambda closed // over an object that holds a reference to this SpriteBatch. - mCommandList = nullptr; + mCustomCallback = nullptr; + mInBeginEndPair = false; + mCommandList = nullptr; } @@ -679,13 +686,22 @@ void SpriteBatch::Impl::PrepareForRendering() // Set the index buffer. commandList->IASetIndexBuffer(&mDeviceResources->indexBufferView); - // Set the transform matrix. - const XMMATRIX transformMatrix = (mRotation == DXGI_MODE_ROTATION_UNSPECIFIED) - ? mTransformMatrix - : (mTransformMatrix * GetViewportTransform(mRotation)); + if (!mCustomCBV) + { + // Set the transform matrix. + const XMMATRIX transformMatrix = (mRotation == DXGI_MODE_ROTATION_UNSPECIFIED) + ? mTransformMatrix + : (mTransformMatrix * GetViewportTransform(mRotation)); + + mConstantBuffer = GraphicsMemory::Get(mDeviceResources->mDevice).AllocateConstant(transformMatrix); + commandList->SetGraphicsRootConstantBufferView(RootParameterIndex::ConstantBuffer, mConstantBuffer.GpuAddress()); + } - mConstantBuffer = GraphicsMemory::Get(mDeviceResources->mDevice).AllocateConstant(transformMatrix); - commandList->SetGraphicsRootConstantBufferView(RootParameterIndex::ConstantBuffer, mConstantBuffer.GpuAddress()); + // Hook lets custom rendering scenarios bind custom resources. + if (mCustomCallback) + { + mCustomCallback(); + } } @@ -1062,20 +1078,60 @@ SpriteBatch& SpriteBatch::operator= (SpriteBatch&&) noexcept = default; SpriteBatch::~SpriteBatch() = default; +// Begin using static sampler +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Begin( + ID3D12GraphicsCommandList* commandList, + SpriteSortMode sortMode, + FXMMATRIX transformMatrix) +{ + pImpl->Begin(commandList, sortMode, transformMatrix); +} + + +// Begin with heap-based sampler +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Begin( + ID3D12GraphicsCommandList* commandList, + D3D12_GPU_DESCRIPTOR_HANDLE sampler, + SpriteSortMode sortMode, + FXMMATRIX transformMatrix) +{ + if (!sampler.ptr) + throw std::invalid_argument("Invalid heap-based sampler for Begin"); + + if (!pImpl->mSampler.ptr) + { + DebugTrace("ERROR: sampler version of Begin requires SpriteBatch was created with a heap-based sampler\n"); + throw std::runtime_error("SpriteBatch::Begin"); + } + + pImpl->mSampler = sampler; + + pImpl->Begin(commandList, sortMode, transformMatrix); +} + + +// Begin using static sampler and custom lambda _Use_decl_annotations_ void XM_CALLCONV SpriteBatch::Begin( ID3D12GraphicsCommandList* commandList, + std::function setCustomCallback, SpriteSortMode sortMode, FXMMATRIX transformMatrix) { + pImpl->mCustomCallback = setCustomCallback; + pImpl->Begin(commandList, sortMode, transformMatrix); } +// Begin with heap-based sampler and custom lambda _Use_decl_annotations_ void XM_CALLCONV SpriteBatch::Begin( ID3D12GraphicsCommandList* commandList, D3D12_GPU_DESCRIPTOR_HANDLE sampler, + std::function setCustomCallback, SpriteSortMode sortMode, FXMMATRIX transformMatrix) { @@ -1089,6 +1145,7 @@ void XM_CALLCONV SpriteBatch::Begin( } pImpl->mSampler = sampler; + pImpl->mCustomCallback = setCustomCallback; pImpl->Begin(commandList, sortMode, transformMatrix); } @@ -1254,3 +1311,8 @@ void SpriteBatch::SetViewport(const D3D12_VIEWPORT& viewPort) pImpl->mSetViewport = true; pImpl->mViewPort = viewPort; } + +void SpriteBatch::GetViewportTransform(XMMATRIX& transformMatrix) const +{ + transformMatrix = pImpl->GetViewportTransform(pImpl->mRotation); +}