diff --git a/include/slang-rhi.h b/include/slang-rhi.h index 5a5aa7e..03060e6 100644 --- a/include/slang-rhi.h +++ b/include/slang-rhi.h @@ -326,7 +326,6 @@ enum class ResourceState { Undefined, General, - PreInitialized, VertexBuffer, IndexBuffer, ConstantBuffer, @@ -344,8 +343,6 @@ enum class ResourceState ResolveDestination, AccelerationStructure, AccelerationStructureBuildInput, - PixelShaderResource, - NonPixelShaderResource, }; /// Describes how memory for the resource should be allocated for CPU access. @@ -1399,12 +1396,10 @@ enum class StoreOp struct RenderPassColorAttachment { ITextureView* view = nullptr; + ITextureView* resolveTarget = nullptr; LoadOp loadOp = LoadOp::DontCare; StoreOp storeOp = StoreOp::Store; float clearValue[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - // TODO: remove with automatic resource tracking - ResourceState initialState = ResourceState::Undefined; - ResourceState finalState = ResourceState::Undefined; }; struct RenderPassDepthStencilAttachment @@ -1418,9 +1413,6 @@ struct RenderPassDepthStencilAttachment StoreOp stencilStoreOp = StoreOp::DontCare; uint8_t stencilClearValue = 0; bool stencilReadOnly = false; - // TODO: remove with automatic resource tracking - ResourceState initialState = ResourceState::Undefined; - ResourceState finalState = ResourceState::Undefined; }; struct RenderPassDesc @@ -1503,27 +1495,14 @@ class ICommandEncoder : public ISlangUnknown public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() = 0; - virtual SLANG_NO_THROW void SLANG_MCALL - textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) = 0; - - inline void textureBarrier(ITexture* texture, ResourceState src, ResourceState dst) - { - textureBarrier(1, &texture, src, dst); - } - - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst - ) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL setBufferState(IBuffer* buffer, ResourceState state) = 0; virtual SLANG_NO_THROW void SLANG_MCALL - bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) = 0; + setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) = 0; - inline void bufferBarrier(IBuffer* buffer, ResourceState src, ResourceState dst) + inline void setTextureState(ITexture* texture, ResourceState state) { - bufferBarrier(1, &buffer, src, dst); + setTextureState(texture, kEntireTexture, state); } virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) = 0; @@ -1545,11 +1524,9 @@ class IResourceCommandEncoder : public ICommandEncoder /// arguments are ignored. virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( ITexture* dst, - ResourceState dstState, SubresourceRange dstSubresource, Offset3D dstOffset, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -1562,7 +1539,6 @@ class IResourceCommandEncoder : public ICommandEncoder Size dstSize, Size dstRowStride, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -1595,15 +1571,6 @@ class IResourceCommandEncoder : public ICommandEncoder bool clearStencil = true ) = 0; - virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( - ITexture* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITexture* dest, - ResourceState destState, - SubresourceRange destRange - ) = 0; - virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery(IQueryPool* queryPool, GfxIndex index, GfxCount count, IBuffer* buffer, Offset offset) = 0; }; @@ -2418,13 +2385,8 @@ class IDevice : public ISlangUnknown createRayTracingPipeline(const RayTracingPipelineDesc& desc, IPipeline** outPipeline) = 0; /// Read back texture resource and stores the result in `outBlob`. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTexture( - ITexture* resource, - ResourceState state, - ISlangBlob** outBlob, - Size* outRowPitch, - Size* outPixelSize - ) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + readTexture(ITexture* texture, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) = 0; virtual SLANG_NO_THROW SlangResult SLANG_MCALL readBuffer(IBuffer* buffer, Offset offset, Size size, ISlangBlob** outBlob) = 0; diff --git a/src/command-encoder-com-forward.h b/src/command-encoder-com-forward.h index 7bae3c2..0d92eb7 100644 --- a/src/command-encoder-com-forward.h +++ b/src/command-encoder-com-forward.h @@ -13,24 +13,14 @@ { \ return CommandEncoderBase::release(); \ } \ - virtual SLANG_NO_THROW void SLANG_MCALL \ - textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) override \ + virtual SLANG_NO_THROW void SLANG_MCALL setBufferState(IBuffer* buffer, ResourceState state) override \ { \ - CommandEncoderBase::textureBarrier(count, textures, src, dst); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( \ - ITexture* texture, \ - SubresourceRange subresourceRange, \ - ResourceState src, \ - ResourceState dst \ - ) override \ - { \ - CommandEncoderBase::textureSubresourceBarrier(texture, subresourceRange, src, dst); \ + CommandEncoderBase::setBufferState(buffer, state); \ } \ virtual SLANG_NO_THROW void SLANG_MCALL \ - bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) override \ + setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) override \ { \ - CommandEncoderBase::bufferBarrier(count, buffers, src, dst); \ + CommandEncoderBase::setTextureState(texture, subresourceRange, state); \ } \ virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, GfxIndex index) override \ { \ diff --git a/src/cuda/cuda-command-encoder.cpp b/src/cuda/cuda-command-encoder.cpp index 36826b8..8660182 100644 --- a/src/cuda/cuda-command-encoder.cpp +++ b/src/cuda/cuda-command-encoder.cpp @@ -11,33 +11,17 @@ void CommandEncoderImpl::init(CommandBufferImpl* cmdBuffer) m_writer = cmdBuffer; } -void CommandEncoderImpl::textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) +void CommandEncoderImpl::setBufferState(IBuffer* buffer, ResourceState state) { - SLANG_UNUSED(count); - SLANG_UNUSED(textures); - SLANG_UNUSED(src); - SLANG_UNUSED(dst); + SLANG_UNUSED(buffer); + SLANG_UNUSED(state); } -void CommandEncoderImpl::textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst -) +void CommandEncoderImpl::setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) { SLANG_UNUSED(texture); SLANG_UNUSED(subresourceRange); - SLANG_UNUSED(src); - SLANG_UNUSED(dst); -} - -void CommandEncoderImpl::bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) -{ - SLANG_UNUSED(count); - SLANG_UNUSED(buffers); - SLANG_UNUSED(src); - SLANG_UNUSED(dst); + SLANG_UNUSED(state); } void CommandEncoderImpl::beginDebugEvent(const char* name, float rgbColor[3]) @@ -67,22 +51,18 @@ void ResourceCommandEncoderImpl::uploadBufferData(IBuffer* dst, Offset offset, S void ResourceCommandEncoderImpl::copyTexture( ITexture* dst, - ResourceState dstState, SubresourceRange dstSubresource, Offset3D dstOffset, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent ) { SLANG_UNUSED(dst); - SLANG_UNUSED(dstState); SLANG_UNUSED(dstSubresource); SLANG_UNUSED(dstOffset); SLANG_UNUSED(src); - SLANG_UNUSED(srcState); SLANG_UNUSED(srcSubresource); SLANG_UNUSED(srcOffset); SLANG_UNUSED(extent); @@ -130,24 +110,6 @@ void ResourceCommandEncoderImpl::clearTexture( SLANG_RHI_UNIMPLEMENTED("clearBuffer"); } -void ResourceCommandEncoderImpl::resolveResource( - ITexture* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITexture* dest, - ResourceState destState, - SubresourceRange destRange -) -{ - SLANG_UNUSED(source); - SLANG_UNUSED(sourceState); - SLANG_UNUSED(sourceRange); - SLANG_UNUSED(dest); - SLANG_UNUSED(destState); - SLANG_UNUSED(destRange); - SLANG_RHI_UNIMPLEMENTED("resolveResource"); -} - void ResourceCommandEncoderImpl::resolveQuery( IQueryPool* queryPool, GfxIndex index, @@ -170,7 +132,6 @@ void ResourceCommandEncoderImpl::copyTextureToBuffer( Size dstSize, Size dstRowStride, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -181,7 +142,6 @@ void ResourceCommandEncoderImpl::copyTextureToBuffer( SLANG_UNUSED(dstSize); SLANG_UNUSED(dstRowStride); SLANG_UNUSED(src); - SLANG_UNUSED(srcState); SLANG_UNUSED(srcSubresource); SLANG_UNUSED(srcOffset); SLANG_UNUSED(extent); diff --git a/src/cuda/cuda-command-encoder.h b/src/cuda/cuda-command-encoder.h index 3fd6e07..2f2f2b1 100644 --- a/src/cuda/cuda-command-encoder.h +++ b/src/cuda/cuda-command-encoder.h @@ -32,18 +32,10 @@ class CommandEncoderImpl : public ICommandEncoder public: void init(CommandBufferImpl* cmdBuffer); - virtual SLANG_NO_THROW void SLANG_MCALL - textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) override; - - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst - ) override; + virtual SLANG_NO_THROW void SLANG_MCALL setBufferState(IBuffer* buffer, ResourceState state) override; virtual SLANG_NO_THROW void SLANG_MCALL - bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) override; + setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) override; virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) override; virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override; @@ -75,11 +67,9 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( ITexture* dst, - ResourceState dstState, SubresourceRange dstSubresource, Offset3D dstOffset, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -104,15 +94,6 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman bool clearStencil ) override; - virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( - ITexture* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITexture* dest, - ResourceState destState, - SubresourceRange destRange - ) override; - virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery(IQueryPool* queryPool, GfxIndex index, GfxCount count, IBuffer* buffer, Offset offset) override; @@ -122,7 +103,6 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman Size dstSize, Size dstRowStride, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent diff --git a/src/cuda/cuda-device.cpp b/src/cuda/cuda-device.cpp index 5322fd2..8599737 100644 --- a/src/cuda/cuda-device.cpp +++ b/src/cuda/cuda-device.cpp @@ -1079,13 +1079,7 @@ Result DeviceImpl::createRenderPipeline(const RenderPipelineDesc& desc, IPipelin return SLANG_E_NOT_AVAILABLE; } -Result DeviceImpl::readTexture( - ITexture* texture, - ResourceState state, - ISlangBlob** outBlob, - size_t* outRowPitch, - size_t* outPixelSize -) +Result DeviceImpl::readTexture(ITexture* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) { auto textureImpl = static_cast(texture); diff --git a/src/cuda/cuda-device.h b/src/cuda/cuda-device.h index 2f157d6..7be986a 100644 --- a/src/cuda/cuda-device.h +++ b/src/cuda/cuda-device.h @@ -100,8 +100,7 @@ class DeviceImpl : public Device createRenderPipeline(const RenderPipelineDesc& desc, IPipeline** outPipeline) override; virtual SLANG_NO_THROW Result SLANG_MCALL - readTexture(ITexture* texture, ResourceState state, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) - override; + readTexture(ITexture* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) override; virtual SLANG_NO_THROW Result SLANG_MCALL readBuffer(IBuffer* buffer, size_t offset, size_t size, ISlangBlob** outBlob) override; diff --git a/src/d3d/d3d-util.cpp b/src/d3d/d3d-util.cpp index 46159c9..12e3dca 100644 --- a/src/d3d/d3d-util.cpp +++ b/src/d3d/d3d-util.cpp @@ -922,8 +922,6 @@ D3D12_RESOURCE_STATES D3DUtil::getResourceState(ResourceState state) return D3D12_RESOURCE_STATE_COMMON; case ResourceState::General: return D3D12_RESOURCE_STATE_COMMON; - case ResourceState::PreInitialized: - return D3D12_RESOURCE_STATE_COMMON; case ResourceState::VertexBuffer: return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; case ResourceState::IndexBuffer: @@ -935,10 +933,6 @@ D3D12_RESOURCE_STATES D3DUtil::getResourceState(ResourceState state) case ResourceState::ShaderResource: case ResourceState::AccelerationStructureBuildInput: return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; - case ResourceState::PixelShaderResource: - return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - case ResourceState::NonPixelShaderResource: - return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; case ResourceState::UnorderedAccess: return D3D12_RESOURCE_STATE_UNORDERED_ACCESS; case ResourceState::RenderTarget: diff --git a/src/d3d11/d3d11-device.cpp b/src/d3d11/d3d11-device.cpp index fbf3038..71ecdef 100644 --- a/src/d3d11/d3d11-device.cpp +++ b/src/d3d11/d3d11-device.cpp @@ -408,36 +408,28 @@ void DeviceImpl::setStencilReference(uint32_t referenceValue) m_depthStencilStateDirty = true; } -Result DeviceImpl::readTexture( - ITexture* resource, - ResourceState state, - ISlangBlob** outBlob, - size_t* outRowPitch, - size_t* outPixelSize -) +Result DeviceImpl::readTexture(ITexture* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) { - SLANG_UNUSED(state); - - auto texture = static_cast(resource); + auto textureImpl = static_cast(texture); // Don't bother supporting MSAA for right now - if (texture->m_desc.sampleCount > 1) + if (textureImpl->m_desc.sampleCount > 1) { fprintf(stderr, "ERROR: cannot capture multi-sample texture\n"); return E_INVALIDARG; } FormatInfo sizeInfo; - rhiGetFormatInfo(texture->m_desc.format, &sizeInfo); + rhiGetFormatInfo(textureImpl->m_desc.format, &sizeInfo); size_t bytesPerPixel = sizeInfo.blockSizeInBytes / sizeInfo.pixelsPerBlock; - size_t rowPitch = int(texture->m_desc.size.width) * bytesPerPixel; - size_t bufferSize = rowPitch * int(texture->m_desc.size.height); + size_t rowPitch = int(textureImpl->m_desc.size.width) * bytesPerPixel; + size_t bufferSize = rowPitch * int(textureImpl->m_desc.size.height); if (outRowPitch) *outRowPitch = rowPitch; if (outPixelSize) *outPixelSize = bytesPerPixel; D3D11_TEXTURE2D_DESC textureDesc; - auto d3d11Texture = ((ID3D11Texture2D*)texture->m_resource.get()); + auto d3d11Texture = ((ID3D11Texture2D*)textureImpl->m_resource.get()); d3d11Texture->GetDesc(&textureDesc); HRESULT hr = S_OK; diff --git a/src/d3d11/d3d11-device.h b/src/d3d11/d3d11-device.h index 59fb261..0e28a0a 100644 --- a/src/d3d11/d3d11-device.h +++ b/src/d3d11/d3d11-device.h @@ -55,8 +55,7 @@ class DeviceImpl : public ImmediateDevice virtual void unmap(IBuffer* buffer, size_t offsetWritten, size_t sizeWritten) override; virtual void copyBuffer(IBuffer* dst, size_t dstOffset, IBuffer* src, size_t srcOffset, size_t size) override; virtual SLANG_NO_THROW Result SLANG_MCALL - readTexture(ITexture* texture, ResourceState state, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) - override; + readTexture(ITexture* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) override; virtual void setVertexBuffers( GfxIndex startSlot, diff --git a/src/d3d12/d3d12-command-buffer.cpp b/src/d3d12/d3d12-command-buffer.cpp index edde1b6..5eb1333 100644 --- a/src/d3d12/d3d12-command-buffer.cpp +++ b/src/d3d12/d3d12-command-buffer.cpp @@ -21,6 +21,107 @@ Result CommandBufferImpl::getNativeHandle(NativeHandle* handle) return SLANG_OK; } +void CommandBufferImpl::requireBufferState(BufferImpl* buffer, ResourceState state) +{ + m_stateTracking.setBufferState(buffer, state); +} + +void CommandBufferImpl::requireTextureState( + TextureImpl* texture, + SubresourceRange subresourceRange, + ResourceState state +) +{ + m_stateTracking.setTextureState(texture, subresourceRange, state); +} + +void CommandBufferImpl::commitBarriers() +{ + short_vector barriers; + + for (const auto& bufferBarrier : m_stateTracking.getBufferBarriers()) + { + BufferImpl* buffer = static_cast(bufferBarrier.buffer); + D3D12_RESOURCE_BARRIER barrier = {}; + bool isUAVBarrier = + (bufferBarrier.stateBefore == bufferBarrier.stateAfter && + bufferBarrier.stateAfter == ResourceState::UnorderedAccess); + if (isUAVBarrier) + { + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barrier.UAV.pResource = buffer->m_resource; + } + else + { + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.pResource = buffer->m_resource; + barrier.Transition.StateBefore = D3DUtil::getResourceState(bufferBarrier.stateBefore); + barrier.Transition.StateAfter = D3DUtil::getResourceState(bufferBarrier.stateAfter); + barrier.Transition.Subresource = 0; + } + barriers.push_back(barrier); + } + + for (const auto& textureBarrier : m_stateTracking.getTextureBarriers()) + { + TextureImpl* texture = static_cast(textureBarrier.texture); + D3D12_RESOURCE_BARRIER barrier = {}; + if (textureBarrier.entireTexture) + { + bool isUAVBarrier = + (textureBarrier.stateBefore == textureBarrier.stateAfter && + textureBarrier.stateAfter == ResourceState::UnorderedAccess); + if (isUAVBarrier) + { + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barrier.UAV.pResource = texture->m_resource; + } + else + { + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.pResource = texture->m_resource; + barrier.Transition.StateBefore = D3DUtil::getResourceState(textureBarrier.stateBefore); + barrier.Transition.StateAfter = D3DUtil::getResourceState(textureBarrier.stateAfter); + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + } + barriers.push_back(barrier); + } + else + { + uint32_t mipLevelCount = texture->m_desc.numMipLevels; + uint32_t arrayLayerCount = + texture->m_desc.arrayLength * (texture->m_desc.type == TextureType::TextureCube ? 6 : 1); + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.pResource = texture->m_resource; + barrier.Transition.StateBefore = D3DUtil::getResourceState(textureBarrier.stateBefore); + barrier.Transition.StateAfter = D3DUtil::getResourceState(textureBarrier.stateAfter); + auto d3dFormat = D3DUtil::getMapFormat(texture->m_desc.format); + auto aspectMask = (int32_t)TextureAspect::Color; + while (aspectMask) + { + auto aspect = math::getLowestBit((int32_t)aspectMask); + aspectMask &= ~aspect; + auto planeIndex = D3DUtil::getPlaneSlice(d3dFormat, (TextureAspect)aspect); + barrier.Transition.Subresource = D3DUtil::getSubresourceIndex( + textureBarrier.mipLevel, + textureBarrier.arrayLayer, + planeIndex, + mipLevelCount, + arrayLayerCount + ); + barriers.push_back(barrier); + } + } + } + + if (!barriers.empty()) + { + m_cmdList->ResourceBarrier((UINT)barriers.size(), barriers.data()); + } + + m_stateTracking.clearBarriers(); +} + void CommandBufferImpl::bindDescriptorHeaps() { if (!m_descriptorHeapsBound) @@ -105,6 +206,11 @@ Result CommandBufferImpl::encodeRayTracingCommands(IRayTracingCommandEncoder** o void CommandBufferImpl::close() { + // Transition all resources back to their default states. + m_stateTracking.requireDefaultStates(); + commitBarriers(); + m_stateTracking.clear(); + m_cmdList->Close(); } diff --git a/src/d3d12/d3d12-command-buffer.h b/src/d3d12/d3d12-command-buffer.h index 8750da8..be09bd1 100644 --- a/src/d3d12/d3d12-command-buffer.h +++ b/src/d3d12/d3d12-command-buffer.h @@ -4,6 +4,8 @@ #include "d3d12-command-encoder.h" #include "d3d12-shader-object.h" +#include "../state-tracking.h" + #ifndef __ID3D12GraphicsCommandList1_FWD_DEFINED__ // If can't find a definition of CommandList1, just use an empty definition struct ID3D12GraphicsCommandList1 @@ -39,6 +41,12 @@ class CommandBufferImpl : public ICommandBufferD3D12, public ComObject RefPtr m_mutableRootShaderObject; bool m_descriptorHeapsBound = false; + StateTracking m_stateTracking; + + void requireBufferState(BufferImpl* buffer, ResourceState state); + void requireTextureState(TextureImpl* texture, SubresourceRange subresourceRange, ResourceState state); + void commitBarriers(); + void bindDescriptorHeaps(); virtual SLANG_NO_THROW void SLANG_MCALL invalidateDescriptorHeapBinding() override diff --git a/src/d3d12/d3d12-command-encoder.cpp b/src/d3d12/d3d12-command-encoder.cpp index 2fe1082..1a35335 100644 --- a/src/d3d12/d3d12-command-encoder.cpp +++ b/src/d3d12/d3d12-command-encoder.cpp @@ -18,126 +18,14 @@ namespace rhi::d3d12 { // CommandEncoderImpl -void CommandEncoderImpl::textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) +void CommandEncoderImpl::setBufferState(IBuffer* buffer, ResourceState state) { - short_vector barriers; - - for (GfxIndex i = 0; i < count; i++) - { - auto textureImpl = static_cast(textures[i]); - auto d3dFormat = D3DUtil::getMapFormat(textureImpl->m_desc.format); - D3D12_RESOURCE_BARRIER barrier; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - if (src == dst && src == ResourceState::UnorderedAccess) - { - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; - barrier.UAV.pResource = textureImpl->m_resource.getResource(); - } - else - { - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Transition.StateBefore = D3DUtil::getResourceState(src); - barrier.Transition.StateAfter = D3DUtil::getResourceState(dst); - if (barrier.Transition.StateBefore == barrier.Transition.StateAfter) - continue; - barrier.Transition.pResource = textureImpl->m_resource.getResource(); - auto planeCount = D3DUtil::getPlaneSliceCount(D3DUtil::getMapFormat(textureImpl->m_desc.format)); - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - } - barriers.push_back(barrier); - } - if (!barriers.empty()) - { - m_commandBuffer->m_cmdList->ResourceBarrier((UINT)barriers.size(), barriers.data()); - } -} - -void CommandEncoderImpl::textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst -) -{ - auto textureImpl = static_cast(texture); - - short_vector barriers; - D3D12_RESOURCE_BARRIER barrier; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - if (src == dst && src == ResourceState::UnorderedAccess) - { - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; - barrier.UAV.pResource = textureImpl->m_resource.getResource(); - barriers.push_back(barrier); - } - else - { - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Transition.StateBefore = D3DUtil::getResourceState(src); - barrier.Transition.StateAfter = D3DUtil::getResourceState(dst); - if (barrier.Transition.StateBefore == barrier.Transition.StateAfter) - return; - barrier.Transition.pResource = textureImpl->m_resource.getResource(); - auto d3dFormat = D3DUtil::getMapFormat(textureImpl->m_desc.format); - auto aspectMask = (int32_t)subresourceRange.aspectMask; - if (subresourceRange.aspectMask == TextureAspect::Default) - aspectMask = (int32_t)TextureAspect::Color; - while (aspectMask) - { - auto aspect = math::getLowestBit((int32_t)aspectMask); - aspectMask &= ~aspect; - auto planeIndex = D3DUtil::getPlaneSlice(d3dFormat, (TextureAspect)aspect); - for (GfxCount layer = 0; layer < subresourceRange.layerCount; layer++) - { - for (GfxCount mip = 0; mip < subresourceRange.mipLevelCount; mip++) - { - barrier.Transition.Subresource = D3DUtil::getSubresourceIndex( - mip + subresourceRange.mipLevel, - layer + subresourceRange.baseArrayLayer, - planeIndex, - textureImpl->m_desc.numMipLevels, - textureImpl->m_desc.arrayLength - ); - barriers.push_back(barrier); - } - } - } - } - m_commandBuffer->m_cmdList->ResourceBarrier((UINT)barriers.size(), barriers.data()); + m_commandBuffer->m_stateTracking.setBufferState(static_cast(buffer), state); } -void CommandEncoderImpl::bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) +void CommandEncoderImpl::setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) { - short_vector barriers; - for (GfxIndex i = 0; i < count; i++) - { - auto bufferImpl = static_cast(buffers[i]); - - D3D12_RESOURCE_BARRIER barrier = {}; - // If the src == dst, it must be a UAV barrier. - barrier.Type = (src == dst && dst == ResourceState::UnorderedAccess) ? D3D12_RESOURCE_BARRIER_TYPE_UAV - : D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - - if (barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV) - { - barrier.UAV.pResource = bufferImpl->m_resource; - } - else - { - barrier.Transition.pResource = bufferImpl->m_resource; - barrier.Transition.StateBefore = D3DUtil::getResourceState(src); - barrier.Transition.StateAfter = D3DUtil::getResourceState(dst); - barrier.Transition.Subresource = 0; - if (barrier.Transition.StateAfter == barrier.Transition.StateBefore) - continue; - } - barriers.push_back(barrier); - } - if (!barriers.empty()) - { - m_commandBuffer->m_cmdList4->ResourceBarrier((UINT)barriers.size(), barriers.data()); - } + m_commandBuffer->m_stateTracking.setTextureState(static_cast(texture), subresourceRange, state); } void CommandEncoderImpl::beginDebugEvent(const char* name, float rgbColor[3]) @@ -244,6 +132,13 @@ Result CommandEncoderImpl::_bindRenderState(Submitter* submitter, RefPtrsetResourceStates(m_commandBuffer->m_stateTracking); + m_commandBuffer->commitBarriers(); + // We kick off binding of shader objects at the root object, and the objects // themselves will be responsible for allocating, binding, and filling in // any descriptor tables or other root parameters needed. @@ -287,18 +182,20 @@ Result CommandEncoderImpl::_bindRenderState(Submitter* submitter, RefPtr(dst); - auto srcTexture = static_cast(src); + TextureImpl* dstTexture = static_cast(dst); + TextureImpl* srcTexture = static_cast(src); + + m_commandBuffer->requireTextureState(dstTexture, dstSubresource, ResourceState::CopyDestination); + m_commandBuffer->requireTextureState(srcTexture, srcSubresource, ResourceState::CopySource); + m_commandBuffer->commitBarriers(); if (dstSubresource.layerCount == 0 && dstSubresource.mipLevelCount == 0 && srcSubresource.layerCount == 0 && srcSubresource.mipLevelCount == 0) @@ -370,7 +267,11 @@ void ResourceCommandEncoderImpl::uploadTextureData( GfxCount subResourceDataCount ) { - auto dstTexture = static_cast(dst); + TextureImpl* dstTexture = static_cast(dst); + + m_commandBuffer->requireTextureState(dstTexture, subResourceRange, ResourceState::CopyDestination); + m_commandBuffer->commitBarriers(); + auto baseSubresourceIndex = D3DUtil::getSubresourceIndex( subResourceRange.mipLevel, subResourceRange.baseArrayLayer, @@ -570,52 +471,6 @@ void ResourceCommandEncoderImpl::clearResourceView( } #endif -void ResourceCommandEncoderImpl::resolveResource( - ITexture* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITexture* dest, - ResourceState destState, - SubresourceRange destRange -) -{ - TextureImpl* srcTexture = static_cast(source); - const TextureDesc& srcDesc = srcTexture->m_desc; - TextureImpl* dstTexture = static_cast(dest); - const TextureDesc& dstDesc = dstTexture->m_desc; - - for (GfxIndex layer = 0; layer < sourceRange.layerCount; ++layer) - { - for (GfxIndex mip = 0; mip < sourceRange.mipLevelCount; ++mip) - { - auto srcSubresourceIndex = D3DUtil::getSubresourceIndex( - mip + sourceRange.mipLevel, - layer + sourceRange.baseArrayLayer, - 0, - srcDesc.numMipLevels, - srcDesc.arrayLength - ); - auto dstSubresourceIndex = D3DUtil::getSubresourceIndex( - mip + destRange.mipLevel, - layer + destRange.baseArrayLayer, - 0, - dstDesc.numMipLevels, - dstDesc.arrayLength - ); - - DXGI_FORMAT format = D3DUtil::getMapFormat(srcDesc.format); - - m_commandBuffer->m_cmdList->ResolveSubresource( - dstTexture->m_resource.getResource(), - dstSubresourceIndex, - srcTexture->m_resource.getResource(), - srcSubresourceIndex, - format - ); - } - } -} - void ResourceCommandEncoderImpl::resolveQuery( IQueryPool* queryPool, GfxIndex index, @@ -624,6 +479,11 @@ void ResourceCommandEncoderImpl::resolveQuery( Offset offset ) { + BufferImpl* bufferImpl = static_cast(buffer); + + m_commandBuffer->requireBufferState(bufferImpl, ResourceState::CopyDestination); + m_commandBuffer->commitBarriers(); + auto queryBase = static_cast(queryPool); switch (queryBase->m_desc.type) { @@ -632,7 +492,6 @@ void ResourceCommandEncoderImpl::resolveQuery( case QueryType::AccelerationStructureSerializedSize: { auto queryPoolImpl = static_cast(queryPool); - auto bufferImpl = static_cast(buffer); auto srcQueryBuffer = queryPoolImpl->m_buffer->m_resource.getResource(); D3D12_RESOURCE_BARRIER barrier = {}; @@ -680,7 +539,6 @@ void ResourceCommandEncoderImpl::copyTextureToBuffer( Size dstSize, Size dstRowStride, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -688,8 +546,13 @@ void ResourceCommandEncoderImpl::copyTextureToBuffer( { SLANG_RHI_ASSERT(srcSubresource.mipLevelCount <= 1); - auto srcTexture = static_cast(src); - auto dstBuffer = static_cast(dst); + BufferImpl* dstBuffer = static_cast(dst); + TextureImpl* srcTexture = static_cast(src); + + m_commandBuffer->requireBufferState(dstBuffer, ResourceState::CopyDestination); + m_commandBuffer->requireTextureState(srcTexture, srcSubresource, ResourceState::CopySource); + m_commandBuffer->commitBarriers(); + auto baseSubresourceIndex = D3DUtil::getSubresourceIndex( srcSubresource.mipLevel, srcSubresource.baseArrayLayer, @@ -772,8 +635,12 @@ void ResourceCommandEncoderImpl::copyTextureToBuffer( void ResourceCommandEncoderImpl::copyBuffer(IBuffer* dst, Offset dstOffset, IBuffer* src, Offset srcOffset, Size size) { - auto dstBuffer = static_cast(dst); - auto srcBuffer = static_cast(src); + BufferImpl* dstBuffer = static_cast(dst); + BufferImpl* srcBuffer = static_cast(src); + + m_commandBuffer->requireBufferState(dstBuffer, ResourceState::CopyDestination); + m_commandBuffer->requireBufferState(srcBuffer, ResourceState::CopySource); + m_commandBuffer->commitBarriers(); m_commandBuffer->m_cmdList->CopyBufferRegion( dstBuffer->m_resource.getResource(), @@ -786,11 +653,16 @@ void ResourceCommandEncoderImpl::copyBuffer(IBuffer* dst, Offset dstOffset, IBuf void ResourceCommandEncoderImpl::uploadBufferData(IBuffer* dst, Offset offset, Size size, void* data) { + BufferImpl* dstBuffer = static_cast(dst); + + m_commandBuffer->requireBufferState(dstBuffer, ResourceState::CopyDestination); + m_commandBuffer->commitBarriers(); + uploadBufferDataImpl( m_commandBuffer->m_device->m_device, m_commandBuffer->m_cmdList, m_commandBuffer->m_transientHeap, - static_cast(dst), + dstBuffer, offset, size, data @@ -816,20 +688,31 @@ void RenderCommandEncoderImpl::init( m_currentPipeline = nullptr; m_renderTargetViews.resize(desc.colorAttachmentCount); - m_renderTargetFinalStates.resize(desc.colorAttachmentCount); + m_resolveTargetViews.resize(desc.colorAttachmentCount); short_vector renderTargetDescriptors; for (Index i = 0; i < desc.colorAttachmentCount; i++) { m_renderTargetViews[i] = static_cast(desc.colorAttachments[i].view); - m_renderTargetFinalStates[i] = desc.colorAttachments[i].finalState; + m_resolveTargetViews[i] = static_cast(desc.colorAttachments[i].resolveTarget); + m_commandBuffer->requireTextureState( + m_renderTargetViews[i]->m_texture, + m_renderTargetViews[i]->m_desc.subresourceRange, + ResourceState::RenderTarget + ); renderTargetDescriptors.push_back(m_renderTargetViews[i]->getRTV().cpuHandle); } if (desc.depthStencilAttachment) { m_depthStencilView = static_cast(desc.depthStencilAttachment->view); - m_depthStencilFinalState = desc.depthStencilAttachment->finalState; + m_commandBuffer->requireTextureState( + m_depthStencilView->m_texture, + m_depthStencilView->m_desc.subresourceRange, + desc.depthStencilAttachment->depthReadOnly ? ResourceState::DepthRead : ResourceState::DepthWrite + ); } + m_commandBuffer->commitBarriers(); + m_d3dCmdList->OMSetRenderTargets( (UINT)m_renderTargetViews.size(), renderTargetDescriptors.data(), @@ -841,30 +724,6 @@ void RenderCommandEncoderImpl::init( for (Index i = 0; i < m_renderTargetViews.size(); i++) { const auto& attachment = desc.colorAttachments[i]; - - // Transit resource states. - { - D3D12BarrierSubmitter submitter(m_d3dCmdList); - auto resourceViewImpl = m_renderTargetViews[i].get(); - if (resourceViewImpl) - { - auto texture = static_cast(resourceViewImpl->m_texture.get()); - if (texture) - { - D3D12_RESOURCE_STATES initialState; - if (attachment.initialState == ResourceState::Undefined) - { - initialState = texture->m_defaultState; - } - else - { - initialState = D3DUtil::getResourceState(attachment.initialState); - } - texture->m_resource.transition(initialState, D3D12_RESOURCE_STATE_RENDER_TARGET, submitter); - } - } - } - // Clear. if (attachment.loadOp == LoadOp::Clear) { m_d3dCmdList->ClearRenderTargetView(renderTargetDescriptors[i], attachment.clearValue, 0, nullptr); @@ -874,23 +733,6 @@ void RenderCommandEncoderImpl::init( if (desc.depthStencilAttachment) { const auto& attachment = *desc.depthStencilAttachment; - - // Transit resource states. - { - D3D12BarrierSubmitter submitter(m_d3dCmdList); - auto texture = static_cast(m_depthStencilView->m_texture.get()); - D3D12_RESOURCE_STATES initialState; - if (attachment.initialState == ResourceState::Undefined) - { - initialState = texture->m_defaultState; - } - else - { - initialState = D3DUtil::getResourceState(attachment.initialState); - } - texture->m_resource.transition(initialState, D3D12_RESOURCE_STATE_DEPTH_WRITE, submitter); - } - // Clear. uint32_t clearFlags = 0; if (attachment.depthLoadOp == LoadOp::Clear) { @@ -979,28 +821,39 @@ void RenderCommandEncoderImpl::setVertexBuffers( for (GfxIndex i = 0; i < slotCount; i++) { - BufferImpl* buffer = static_cast(buffers[i]); - BoundVertexBuffer& boundBuffer = m_boundVertexBuffers[startSlot + i]; - boundBuffer.m_buffer = buffer; + boundBuffer.m_buffer = static_cast(buffers[i]); boundBuffer.m_offset = int(offsets[i]); } } void RenderCommandEncoderImpl::setIndexBuffer(IBuffer* buffer, IndexFormat indexFormat, Offset offset) { - m_boundIndexBuffer = (BufferImpl*)buffer; + m_boundIndexBuffer = static_cast(buffer); m_boundIndexFormat = D3DUtil::getIndexFormat(indexFormat); m_boundIndexOffset = (UINT)offset; } Result RenderCommandEncoderImpl::prepareDraw() { - auto pipeline = m_currentPipeline.Ptr(); + Pipeline* pipeline = m_currentPipeline.get(); if (!pipeline || (pipeline->desc.type != PipelineType::Graphics)) { return SLANG_FAIL; } + InputLayoutImpl* inputLayout = (InputLayoutImpl*)pipeline->inputLayout.get(); + + if (inputLayout) + { + for (Index i = 0; i < m_boundVertexBuffers.size(); i++) + { + m_commandBuffer->requireBufferState(m_boundVertexBuffers[i].m_buffer, ResourceState::VertexBuffer); + } + } + if (m_boundIndexBuffer) + { + m_commandBuffer->requireBufferState(m_boundIndexBuffer, ResourceState::IndexBuffer); + } // Submit - setting for graphics { @@ -1013,7 +866,6 @@ Result RenderCommandEncoderImpl::prepareDraw() // Set up vertex buffer views { - auto inputLayout = (InputLayoutImpl*)pipeline->inputLayout.Ptr(); if (inputLayout) { int numVertexViews = 0; @@ -1045,6 +897,7 @@ Result RenderCommandEncoderImpl::prepareDraw() m_d3dCmdList->IASetIndexBuffer(&indexBufferView); } + return SLANG_OK; } @@ -1064,41 +917,49 @@ Result RenderCommandEncoderImpl::drawIndexed(GfxCount indexCount, GfxIndex start void RenderCommandEncoderImpl::endEncoding() { - // Issue clear commands based on render pass set up. - for (Index i = 0; i < m_renderTargetViews.size(); i++) + bool needsResolve = false; + for (size_t i = 0; i < m_renderTargetViews.size(); ++i) { - // Transit resource states. - if (m_renderTargetViews[i]) + if (m_renderTargetViews[i] && m_resolveTargetViews[i]) { - D3D12BarrierSubmitter submitter(m_d3dCmdList); - auto texture = static_cast(m_renderTargetViews[i]->m_texture.get()); - if (texture) - { - texture->m_resource.transition( - D3D12_RESOURCE_STATE_RENDER_TARGET, - D3DUtil::getResourceState(m_renderTargetFinalStates[i]), - submitter - ); - } + m_commandBuffer->requireTextureState( + m_renderTargetViews[i]->m_texture, + m_renderTargetViews[i]->m_desc.subresourceRange, + ResourceState::ResolveSource + ); + m_commandBuffer->requireTextureState( + m_resolveTargetViews[i]->m_texture, + m_resolveTargetViews[i]->m_desc.subresourceRange, + ResourceState::ResolveDestination + ); + needsResolve = true; } } - if (m_depthStencilView) + if (needsResolve) { - // Transit resource states. - D3D12BarrierSubmitter submitter(m_d3dCmdList); - auto texture = static_cast(m_depthStencilView->m_texture.get()); - if (texture) + m_commandBuffer->commitBarriers(); + + for (size_t i = 0; i < m_renderTargetViews.size(); ++i) { - texture->m_resource.transition( - D3D12_RESOURCE_STATE_DEPTH_WRITE, - D3DUtil::getResourceState(m_depthStencilFinalState), - submitter - ); + if (m_renderTargetViews[i] && m_resolveTargetViews[i]) + { + TextureViewImpl* srcView = m_renderTargetViews[i].get(); + TextureViewImpl* dstView = m_resolveTargetViews[i].get(); + DXGI_FORMAT format = D3DUtil::getMapFormat(srcView->m_texture->m_desc.format); + m_commandBuffer->m_cmdList->ResolveSubresource( + dstView->m_texture->m_resource.getResource(), + 0, // TODO iterate subresources + srcView->m_texture->m_resource.getResource(), + 0, // TODO iterate subresources + format + ); + } } } m_renderTargetViews.clear(); + m_resolveTargetViews.clear(); m_depthStencilView = nullptr; CommandEncoderImpl::endEncodingImpl(); @@ -1117,10 +978,16 @@ Result RenderCommandEncoderImpl::drawIndirect( Offset countOffset ) { - SLANG_RETURN_ON_FAIL(prepareDraw()); + BufferImpl* argBufferImpl = static_cast(argBuffer); + BufferImpl* countBufferImpl = static_cast(countBuffer); - auto argBufferImpl = static_cast(argBuffer); - auto countBufferImpl = static_cast(countBuffer); + m_commandBuffer->requireBufferState(argBufferImpl, ResourceState::IndirectArgument); + if (countBufferImpl) + { + m_commandBuffer->requireBufferState(countBufferImpl, ResourceState::IndirectArgument); + } + + SLANG_RETURN_ON_FAIL(prepareDraw()); m_d3dCmdList->ExecuteIndirect( m_device->drawIndirectCmdSignature, @@ -1141,10 +1008,16 @@ Result RenderCommandEncoderImpl::drawIndexedIndirect( Offset countOffset ) { - SLANG_RETURN_ON_FAIL(prepareDraw()); + BufferImpl* argBufferImpl = static_cast(argBuffer); + BufferImpl* countBufferImpl = static_cast(countBuffer); - auto argBufferImpl = static_cast(argBuffer); - auto countBufferImpl = static_cast(countBuffer); + m_commandBuffer->requireBufferState(argBufferImpl, ResourceState::IndirectArgument); + if (countBufferImpl) + { + m_commandBuffer->requireBufferState(countBufferImpl, ResourceState::IndirectArgument); + } + + SLANG_RETURN_ON_FAIL(prepareDraw()); m_d3dCmdList->ExecuteIndirect( m_device->drawIndexedIndirectCmdSignature, @@ -1268,7 +1141,11 @@ Result ComputeCommandEncoderImpl::dispatchComputeIndirect(IBuffer* argBuffer, Of RefPtr newPipeline; SLANG_RETURN_ON_FAIL(_bindRenderState(&submitter, newPipeline)); } - auto argBufferImpl = static_cast(argBuffer); + + BufferImpl* argBufferImpl = static_cast(argBuffer); + + m_commandBuffer->requireBufferState(argBufferImpl, ResourceState::IndirectArgument); + m_commandBuffer->commitBarriers(); m_d3dCmdList->ExecuteIndirect( m_device->dispatchIndirectCmdSignature, diff --git a/src/d3d12/d3d12-command-encoder.h b/src/d3d12/d3d12-command-encoder.h index 2d08c6b..0d8c5be 100644 --- a/src/d3d12/d3d12-command-encoder.h +++ b/src/d3d12/d3d12-command-encoder.h @@ -33,16 +33,10 @@ class CommandEncoderImpl : public ICommandEncoder virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; } public: + // ICommandEncoder implementation + virtual SLANG_NO_THROW void SLANG_MCALL setBufferState(IBuffer* buffer, ResourceState state) override; virtual SLANG_NO_THROW void SLANG_MCALL - textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) override; - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst - ) override; - virtual SLANG_NO_THROW void SLANG_MCALL - bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) override; + setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) override; virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) override; virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override; @@ -100,11 +94,9 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override {} virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( ITexture* dst, - ResourceState dstState, SubresourceRange dstSubresource, Offset3D dstOffset, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -129,15 +121,6 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman bool clearStencil ) override; - virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( - ITexture* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITexture* dest, - ResourceState destState, - SubresourceRange destRange - ) override; - virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery(IQueryPool* queryPool, GfxIndex index, GfxCount count, IBuffer* buffer, Offset offset) override; @@ -147,7 +130,6 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman Size dstSize, Size dstRowStride, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -174,12 +156,10 @@ class RenderCommandEncoderImpl : public IRenderCommandEncoder, public CommandEnc public: short_vector> m_renderTargetViews; - short_vector m_renderTargetFinalStates; + short_vector> m_resolveTargetViews; RefPtr m_depthStencilView; - ResourceState m_depthStencilFinalState; std::vector m_boundVertexBuffers; - RefPtr m_boundIndexBuffer; D3D12_VIEWPORT m_viewports[kMaxRTVCount]; @@ -211,6 +191,7 @@ class RenderCommandEncoderImpl : public IRenderCommandEncoder, public CommandEnc setIndexBuffer(IBuffer* buffer, IndexFormat indexFormat, Offset offset = 0) override; Result prepareDraw(); + virtual SLANG_NO_THROW Result SLANG_MCALL draw(GfxCount vertexCount, GfxIndex startVertex = 0) override; virtual SLANG_NO_THROW Result SLANG_MCALL drawIndexed(GfxCount indexCount, GfxIndex startIndex = 0, GfxIndex baseVertex = 0) override; diff --git a/src/d3d12/d3d12-device.cpp b/src/d3d12/d3d12-device.cpp index 5e4b7a9..fa05d82 100644 --- a/src/d3d12/d3d12-device.cpp +++ b/src/d3d12/d3d12-device.cpp @@ -164,115 +164,6 @@ Result DeviceImpl::createBuffer( return SLANG_OK; } -Result DeviceImpl::captureTextureToSurface( - TextureImpl* resourceImpl, - ResourceState state, - ISlangBlob** outBlob, - Size* outRowPitch, - Size* outPixelSize -) -{ - auto& resource = resourceImpl->m_resource; - - const D3D12_RESOURCE_STATES initialState = D3DUtil::getResourceState(state); - - const TextureDesc& rhiDesc = resourceImpl->getDesc(); - const D3D12_RESOURCE_DESC desc = resource.getResource()->GetDesc(); - - // Don't bother supporting MSAA for right now - if (desc.SampleDesc.Count > 1) - { - fprintf(stderr, "ERROR: cannot capture multi-sample texture\n"); - return SLANG_FAIL; - } - - FormatInfo formatInfo; - rhiGetFormatInfo(rhiDesc.format, &formatInfo); - Size bytesPerPixel = formatInfo.blockSizeInBytes / formatInfo.pixelsPerBlock; - Size rowPitch = int(desc.Width) * bytesPerPixel; - static const Size align = 256; // D3D requires minimum 256 byte alignment for texture data. - rowPitch = (rowPitch + align - 1) & ~(align - 1); // Bit trick for rounding up - Size bufferSize = rowPitch * int(desc.Height) * int(desc.DepthOrArraySize); - if (outRowPitch) - *outRowPitch = rowPitch; - if (outPixelSize) - *outPixelSize = bytesPerPixel; - - D3D12Resource stagingResource; - { - D3D12_RESOURCE_DESC stagingDesc; - initBufferDesc(bufferSize, stagingDesc); - - D3D12_HEAP_PROPERTIES heapProps; - heapProps.Type = D3D12_HEAP_TYPE_READBACK; - heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; - heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; - heapProps.CreationNodeMask = 1; - heapProps.VisibleNodeMask = 1; - - SLANG_RETURN_ON_FAIL(stagingResource.initCommitted( - m_device, - heapProps, - D3D12_HEAP_FLAG_NONE, - stagingDesc, - D3D12_RESOURCE_STATE_COPY_DEST, - nullptr - )); - } - - auto encodeInfo = encodeResourceCommands(); - auto currentState = D3DUtil::getResourceState(state); - - { - D3D12BarrierSubmitter submitter(encodeInfo.d3dCommandList); - resource.transition(currentState, D3D12_RESOURCE_STATE_COPY_SOURCE, submitter); - } - - // Do the copy - { - D3D12_TEXTURE_COPY_LOCATION srcLoc; - srcLoc.pResource = resource; - srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - srcLoc.SubresourceIndex = 0; - - D3D12_TEXTURE_COPY_LOCATION dstLoc; - dstLoc.pResource = stagingResource; - dstLoc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - dstLoc.PlacedFootprint.Offset = 0; - dstLoc.PlacedFootprint.Footprint.Format = desc.Format; - dstLoc.PlacedFootprint.Footprint.Width = UINT(desc.Width); - dstLoc.PlacedFootprint.Footprint.Height = UINT(desc.Height); - dstLoc.PlacedFootprint.Footprint.Depth = UINT(desc.DepthOrArraySize); - dstLoc.PlacedFootprint.Footprint.RowPitch = UINT(rowPitch); - - encodeInfo.d3dCommandList->CopyTextureRegion(&dstLoc, 0, 0, 0, &srcLoc, nullptr); - } - - { - D3D12BarrierSubmitter submitter(encodeInfo.d3dCommandList); - resource.transition(D3D12_RESOURCE_STATE_COPY_SOURCE, currentState, submitter); - } - - // Submit the copy, and wait for copy to complete - submitResourceCommandsAndWait(encodeInfo); - - { - ID3D12Resource* dxResource = stagingResource; - - UINT8* data; - D3D12_RANGE readRange = {0, bufferSize}; - - SLANG_RETURN_ON_FAIL(dxResource->Map(0, &readRange, reinterpret_cast(&data))); - - auto blob = OwnedBlob::create(bufferSize); - memcpy((void*)blob->getBufferPointer(), data, bufferSize); - dxResource->Unmap(0, nullptr); - - returnComPtr(outBlob, blob); - return SLANG_OK; - } -} - Result DeviceImpl::getNativeDeviceHandles(NativeHandles* outHandles) { outHandles->handles[0].type = NativeHandleType::D3D12Device; @@ -981,15 +872,107 @@ Result DeviceImpl::createSwapchain(const ISwapchain::Desc& desc, WindowHandle wi return SLANG_OK; } -Result DeviceImpl::readTexture( - ITexture* resource, - ResourceState state, - ISlangBlob** outBlob, - Size* outRowPitch, - Size* outPixelSize -) +Result DeviceImpl::readTexture(ITexture* texture, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) { - return captureTextureToSurface(static_cast(resource), state, outBlob, outRowPitch, outPixelSize); + TextureImpl* textureImpl = static_cast(texture); + + auto& resource = textureImpl->m_resource; + + const TextureDesc& rhiDesc = textureImpl->getDesc(); + const D3D12_RESOURCE_DESC desc = resource.getResource()->GetDesc(); + + // Don't bother supporting MSAA for right now + if (desc.SampleDesc.Count > 1) + { + fprintf(stderr, "ERROR: cannot capture multi-sample texture\n"); + return SLANG_FAIL; + } + + FormatInfo formatInfo; + rhiGetFormatInfo(rhiDesc.format, &formatInfo); + Size bytesPerPixel = formatInfo.blockSizeInBytes / formatInfo.pixelsPerBlock; + Size rowPitch = int(desc.Width) * bytesPerPixel; + static const Size align = 256; // D3D requires minimum 256 byte alignment for texture data. + rowPitch = (rowPitch + align - 1) & ~(align - 1); // Bit trick for rounding up + Size bufferSize = rowPitch * int(desc.Height) * int(desc.DepthOrArraySize); + if (outRowPitch) + *outRowPitch = rowPitch; + if (outPixelSize) + *outPixelSize = bytesPerPixel; + + D3D12Resource stagingResource; + { + D3D12_RESOURCE_DESC stagingDesc; + initBufferDesc(bufferSize, stagingDesc); + + D3D12_HEAP_PROPERTIES heapProps; + heapProps.Type = D3D12_HEAP_TYPE_READBACK; + heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heapProps.CreationNodeMask = 1; + heapProps.VisibleNodeMask = 1; + + SLANG_RETURN_ON_FAIL(stagingResource.initCommitted( + m_device, + heapProps, + D3D12_HEAP_FLAG_NONE, + stagingDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr + )); + } + + auto encodeInfo = encodeResourceCommands(); + + auto defaultState = D3DUtil::getResourceState(rhiDesc.defaultState); + { + D3D12BarrierSubmitter submitter(encodeInfo.d3dCommandList); + resource.transition(defaultState, D3D12_RESOURCE_STATE_COPY_SOURCE, submitter); + } + + // Do the copy + { + D3D12_TEXTURE_COPY_LOCATION srcLoc; + srcLoc.pResource = resource; + srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + srcLoc.SubresourceIndex = 0; + + D3D12_TEXTURE_COPY_LOCATION dstLoc; + dstLoc.pResource = stagingResource; + dstLoc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + dstLoc.PlacedFootprint.Offset = 0; + dstLoc.PlacedFootprint.Footprint.Format = desc.Format; + dstLoc.PlacedFootprint.Footprint.Width = UINT(desc.Width); + dstLoc.PlacedFootprint.Footprint.Height = UINT(desc.Height); + dstLoc.PlacedFootprint.Footprint.Depth = UINT(desc.DepthOrArraySize); + dstLoc.PlacedFootprint.Footprint.RowPitch = UINT(rowPitch); + + encodeInfo.d3dCommandList->CopyTextureRegion(&dstLoc, 0, 0, 0, &srcLoc, nullptr); + } + + { + D3D12BarrierSubmitter submitter(encodeInfo.d3dCommandList); + resource.transition(D3D12_RESOURCE_STATE_COPY_SOURCE, defaultState, submitter); + } + + // Submit the copy, and wait for copy to complete + submitResourceCommandsAndWait(encodeInfo); + + { + ID3D12Resource* dxResource = stagingResource; + + UINT8* data; + D3D12_RANGE readRange = {0, bufferSize}; + + SLANG_RETURN_ON_FAIL(dxResource->Map(0, &readRange, reinterpret_cast(&data))); + + auto blob = OwnedBlob::create(bufferSize); + memcpy((void*)blob->getBufferPointer(), data, bufferSize); + dxResource->Unmap(0, nullptr); + + returnComPtr(outBlob, blob); + return SLANG_OK; + } } Result DeviceImpl::getTextureAllocationInfo(const TextureDesc& desc, Size* outSize, Size* outAlignment) diff --git a/src/d3d12/d3d12-device.h b/src/d3d12/d3d12-device.h index d8b8623..3f8d503 100644 --- a/src/d3d12/d3d12-device.h +++ b/src/d3d12/d3d12-device.h @@ -160,11 +160,10 @@ class DeviceImpl : public Device override; virtual SLANG_NO_THROW Result SLANG_MCALL - readTexture(ITexture* resource, ResourceState state, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) - override; + readTexture(ITexture* texture, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) override; virtual SLANG_NO_THROW Result SLANG_MCALL - readBuffer(IBuffer* resource, Offset offset, Size size, ISlangBlob** outBlob) override; + readBuffer(IBuffer* buffer, Offset offset, Size size, ISlangBlob** outBlob) override; virtual SLANG_NO_THROW const DeviceInfo& SLANG_MCALL getDeviceInfo() const override; @@ -206,14 +205,6 @@ class DeviceImpl : public Device MemoryType access = MemoryType::DeviceLocal ); - Result captureTextureToSurface( - TextureImpl* resource, - ResourceState state, - ISlangBlob** blob, - Size* outRowPitch, - Size* outPixelSize - ); - Result _createDevice( DeviceCheckFlags deviceCheckFlags, const AdapterLUID* adapterLUID, diff --git a/src/d3d12/d3d12-helper-functions.h b/src/d3d12/d3d12-helper-functions.h index d2a22b2..2d37a1a 100644 --- a/src/d3d12/d3d12-helper-functions.h +++ b/src/d3d12/d3d12-helper-functions.h @@ -31,8 +31,8 @@ struct BindingContext Submitter* submitter; TransientResourceHeapImpl* transientHeap; DeviceImpl* device; - D3D12_DESCRIPTOR_HEAP_TYPE - outOfMemoryHeap; // The type of descriptor heap that is OOM during binding. + /// The type of descriptor heap that is OOM during binding. + D3D12_DESCRIPTOR_HEAP_TYPE outOfMemoryHeap; short_vector* pendingTableBindings; }; diff --git a/src/d3d12/d3d12-shader-object.cpp b/src/d3d12/d3d12-shader-object.cpp index 79210b1..39a96ee 100644 --- a/src/d3d12/d3d12-shader-object.cpp +++ b/src/d3d12/d3d12-shader-object.cpp @@ -130,7 +130,6 @@ Result ShaderObjectImpl::init( // have a counter buffer associated with it, which we // also need to ensure isn't destroyed prematurely. m_boundResources.resize(resourceCount); - m_boundCounterResources.resize(resourceCount); } if (auto samplerCount = layout->getSamplerSlotCount()) { @@ -796,6 +795,43 @@ Result ShaderObjectImpl::bindRootArguments(BindingContext* context, uint32_t& in return SLANG_OK; } +void ShaderObjectImpl::setResourceStates(StateTracking& stateTracking) +{ + for (const BoundResource& boundResource : m_boundResources) + { + switch (boundResource.type) + { + case BoundResourceType::Buffer: + stateTracking.setBufferState( + static_cast(boundResource.resource.get()), + boundResource.requiredState + ); + break; + case BoundResourceType::TextureView: + { + TextureViewImpl* textureView = static_cast(boundResource.resource.get()); + stateTracking.setTextureState( + textureView->m_texture, + textureView->m_desc.subresourceRange, + boundResource.requiredState + ); + break; + } + case BoundResourceType::AccelerationStructure: + // TODO STATE_TRACKING need state transition? + break; + } + } + + for (auto& subObject : m_objects) + { + if (subObject) + { + subObject->setResourceStates(stateTracking); + } + } +} + /// Get the layout of this shader object with specialization arguments considered /// /// This operation should only be called after the shader object has been @@ -851,6 +887,8 @@ Result ShaderObjectImpl::setBinding(ShaderOffset const& offset, Binding binding) Index bindingIndex = bindingRange.baseIndex + offset.bindingArrayIndex; + BoundResource& boundResource = m_boundResources[bindingIndex]; + switch (binding.type) { case BindingType::Buffer: @@ -859,8 +897,9 @@ Result ShaderObjectImpl::setBinding(ShaderOffset const& offset, Binding binding) BufferImpl* buffer = static_cast(binding.resource.get()); BufferImpl* counterBuffer = static_cast(binding.resource2.get()); BufferRange bufferRange = buffer->resolveBufferRange(binding.bufferRange); - m_boundResources[bindingIndex] = buffer; - m_boundCounterResources[bindingIndex] = counterBuffer; + boundResource.type = BoundResourceType::Buffer; + boundResource.resource = buffer; + boundResource.counterResource = counterBuffer; if (bindingRange.isRootParameter) { m_rootArguments[bindingRange.baseIndex] = buffer->getDeviceAddress() + bufferRange.offset; @@ -872,16 +911,20 @@ Result ShaderObjectImpl::setBinding(ShaderOffset const& offset, Binding binding) { case slang::BindingType::TypedBuffer: descriptor = buffer->getSRV(buffer->m_desc.format, 0, bufferRange); + boundResource.requiredState = ResourceState::ShaderResource; break; case slang::BindingType::RawBuffer: descriptor = buffer->getSRV(Format::Unknown, bindingRange.bufferElementStride, bufferRange); + boundResource.requiredState = ResourceState::ShaderResource; break; case slang::BindingType::MutableTypedBuffer: descriptor = buffer->getUAV(buffer->m_desc.format, 0, bufferRange); + boundResource.requiredState = ResourceState::UnorderedAccess; break; case slang::BindingType::MutableRawBuffer: descriptor = buffer->getUAV(Format::Unknown, bindingRange.bufferElementStride, bufferRange, counterBuffer); + boundResource.requiredState = ResourceState::UnorderedAccess; break; default: return SLANG_FAIL; @@ -903,15 +946,18 @@ Result ShaderObjectImpl::setBinding(ShaderOffset const& offset, Binding binding) case BindingType::TextureView: { TextureViewImpl* textureView = static_cast(binding.resource.get()); - m_boundResources[bindingIndex] = textureView; + boundResource.type = BoundResourceType::TextureView; + boundResource.resource = textureView; D3D12Descriptor descriptor; switch (bindingRange.bindingType) { case slang::BindingType::Texture: descriptor = textureView->getSRV(); + boundResource.requiredState = ResourceState::ShaderResource; break; case slang::BindingType::MutableTexture: descriptor = textureView->getUAV(); + boundResource.requiredState = ResourceState::UnorderedAccess; break; default: return SLANG_FAIL; @@ -939,6 +985,9 @@ Result ShaderObjectImpl::setBinding(ShaderOffset const& offset, Binding binding) { TextureViewImpl* textureView = static_cast(binding.resource.get()); SamplerImpl* sampler = static_cast(binding.resource2.get()); + boundResource.type = BoundResourceType::TextureView; + boundResource.resource = textureView; + boundResource.requiredState = ResourceState::ShaderResource; d3dDevice->CopyDescriptorsSimple( 1, m_descriptorSet.resourceTable.getCpuHandle(bindingIndex), @@ -956,7 +1005,8 @@ Result ShaderObjectImpl::setBinding(ShaderOffset const& offset, Binding binding) case BindingType::AccelerationStructure: { AccelerationStructureImpl* as = static_cast(binding.resource.get()); - m_boundResources[bindingIndex] = as; + boundResource.type = BoundResourceType::AccelerationStructure; + boundResource.resource = as; if (bindingRange.isRootParameter) { m_rootArguments[bindingRange.baseIndex] = as->getDeviceAddress(); @@ -1126,6 +1176,15 @@ Result RootShaderObjectImpl::copyFrom(IShaderObject* object, ITransientResourceH return SLANG_FAIL; } +void RootShaderObjectImpl::setResourceStates(StateTracking& stateTracking) +{ + ShaderObjectImpl::setResourceStates(stateTracking); + for (auto& entryPoint : m_entryPoints) + { + entryPoint->setResourceStates(stateTracking); + } +} + Result RootShaderObjectImpl::bindAsRoot(BindingContext* context, RootShaderObjectLayoutImpl* specializedLayout) { // Pull updates from sub-objects when this is a mutable root shader object. diff --git a/src/d3d12/d3d12-shader-object.h b/src/d3d12/d3d12-shader-object.h index 435e335..1a6741a 100644 --- a/src/d3d12/d3d12-shader-object.h +++ b/src/d3d12/d3d12-shader-object.h @@ -4,6 +4,8 @@ #include "d3d12-helper-functions.h" #include "d3d12-submitter.h" +#include "../state-tracking.h" + #include "core/short_vector.h" #include @@ -78,6 +80,22 @@ struct DescriptorSet } }; +enum class BoundResourceType +{ + None, + Buffer, + TextureView, + AccelerationStructure, +}; + +struct BoundResource +{ + BoundResourceType type = BoundResourceType::None; + RefPtr resource; + RefPtr counterResource; + ResourceState requiredState = ResourceState::Undefined; +}; + class ShaderObjectImpl : public ShaderObjectBaseImpl { typedef ShaderObjectBaseImpl Super; @@ -185,14 +203,16 @@ class ShaderObjectImpl : public ShaderObjectBaseImpl, 8> m_boundResources; - short_vector, 8> m_boundCounterResources; + short_vector m_boundResources; std::vector m_rootArguments; /// A constant buffer used to stored ordinary data for this object /// and existential-type sub-objects. @@ -255,6 +275,8 @@ class RootShaderObjectImpl : public ShaderObjectImpl copyFrom(IShaderObject* object, ITransientResourceHeap* transientHeap) override; public: + void setResourceStates(StateTracking& stateTracking); + Result bindAsRoot(BindingContext* context, RootShaderObjectLayoutImpl* specializedLayout); public: diff --git a/src/d3d12/d3d12-shader-table.cpp b/src/d3d12/d3d12-shader-table.cpp index 4bbace3..99b273c 100644 --- a/src/d3d12/d3d12-shader-table.cpp +++ b/src/d3d12/d3d12-shader-table.cpp @@ -29,7 +29,7 @@ RefPtr ShaderTableImpl::createDeviceBuffer( ComPtr buffer; BufferDesc bufferDesc = {}; bufferDesc.memoryType = MemoryType::DeviceLocal; - bufferDesc.defaultState = ResourceState::General; + bufferDesc.defaultState = ResourceState::ShaderResource; bufferDesc.usage = BufferUsage::ShaderTable; bufferDesc.size = tableSize; m_device->createBuffer(bufferDesc, nullptr, buffer.writeRef()); @@ -104,7 +104,13 @@ RefPtr ShaderTableImpl::createDeviceBuffer( stagingBufferOffset, tableSize ); - encoder->bufferBarrier(1, buffer.readRef(), ResourceState::CopyDestination, ResourceState::NonPixelShaderResource); + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.pResource = static_cast(buffer.get())->m_resource.getResource(); + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + static_cast(encoder)->m_commandBuffer->m_cmdList->ResourceBarrier(1, &barrier); + RefPtr resultPtr = static_cast(buffer.get()); return _Move(resultPtr); } diff --git a/src/debug-layer/debug-command-buffer.cpp b/src/debug-layer/debug-command-buffer.cpp index 50b72a8..727b82d 100644 --- a/src/debug-layer/debug-command-buffer.cpp +++ b/src/debug-layer/debug-command-buffer.cpp @@ -34,6 +34,8 @@ Result DebugCommandBuffer::encodeResourceCommands(IResourceCommandEncoder** outE Result DebugCommandBuffer::encodeRenderCommands(const RenderPassDesc& desc, IRenderCommandEncoder** outEncoder) { + // TODO VALIDATION: resolveTarget must have usage RenderTarget (Vulkan, WGPU) + SLANG_RHI_API_FUNC; checkCommandBufferOpenWhenCreatingEncoder(); checkEncodersClosedBeforeNewEncoder(); @@ -43,6 +45,7 @@ Result DebugCommandBuffer::encodeRenderCommands(const RenderPassDesc& desc, IRen { innerColorAttachments.push_back(desc.colorAttachments[i]); innerColorAttachments[i].view = getInnerObj(desc.colorAttachments[i].view); + innerColorAttachments[i].resolveTarget = getInnerObj(desc.colorAttachments[i].resolveTarget); } innerDesc.colorAttachments = innerColorAttachments.data(); RenderPassDepthStencilAttachment innerDepthStencilAttachment; diff --git a/src/debug-layer/debug-command-encoder.cpp b/src/debug-layer/debug-command-encoder.cpp index 967b972..bed7a89 100644 --- a/src/debug-layer/debug-command-encoder.cpp +++ b/src/debug-layer/debug-command-encoder.cpp @@ -13,42 +13,16 @@ namespace rhi::debug { // DebugCommandEncoder -void DebugCommandEncoder::textureBarrier( - GfxCount count, - ITexture* const* textures, - ResourceState src, - ResourceState dst -) -{ - SLANG_RHI_API_FUNC; - std::vector innerTextures; - for (GfxIndex i = 0; i < count; i++) - { - innerTextures.push_back(static_cast(textures[i])->baseObject.get()); - } - getBaseObject()->textureBarrier(count, innerTextures.data(), src, dst); -} - -void DebugCommandEncoder::textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst -) +void DebugCommandEncoder::setBufferState(IBuffer* buffer, ResourceState state) { SLANG_RHI_API_FUNC; - getBaseObject()->textureSubresourceBarrier(getInnerObj(texture), subresourceRange, src, dst); + getBaseObject()->setBufferState(getInnerObj(buffer), state); } -void DebugCommandEncoder::bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) +void DebugCommandEncoder::setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) { SLANG_RHI_API_FUNC; - std::vector innerBuffers; - for (GfxIndex i = 0; i < count; i++) - { - innerBuffers.push_back(static_cast(buffers[i])->baseObject.get()); - } - getBaseObject()->bufferBarrier(count, innerBuffers.data(), src, dst); + getBaseObject()->setTextureState(getInnerObj(texture), subresourceRange, state); } void DebugCommandEncoder::beginDebugEvent(const char* name, float rgbColor[3]) @@ -94,28 +68,17 @@ void DebugResourceCommandEncoder::uploadBufferData(IBuffer* dst, Offset offset, void DebugResourceCommandEncoder::copyTexture( ITexture* dst, - ResourceState dstState, SubresourceRange dstSubresource, Offset3D dstOffset, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent ) { SLANG_RHI_API_FUNC; - baseObject->copyTexture( - getInnerObj(dst), - dstState, - dstSubresource, - dstOffset, - getInnerObj(src), - srcState, - srcSubresource, - srcOffset, - extent - ); + baseObject + ->copyTexture(getInnerObj(dst), dstSubresource, dstOffset, getInnerObj(src), srcSubresource, srcOffset, extent); } void DebugResourceCommandEncoder::uploadTextureData( @@ -150,19 +113,6 @@ void DebugResourceCommandEncoder::clearTexture( baseObject->clearTexture(getInnerObj(texture), clearValue, subresourceRange, clearDepth, clearStencil); } -void DebugResourceCommandEncoder::resolveResource( - ITexture* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITexture* dest, - ResourceState destState, - SubresourceRange destRange -) -{ - SLANG_RHI_API_FUNC; - baseObject->resolveResource(getInnerObj(source), sourceState, sourceRange, getInnerObj(dest), destState, destRange); -} - void DebugResourceCommandEncoder::resolveQuery( IQueryPool* queryPool, GfxIndex index, @@ -181,7 +131,6 @@ void DebugResourceCommandEncoder::copyTextureToBuffer( Size dstSize, Size dstRowStride, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -194,7 +143,6 @@ void DebugResourceCommandEncoder::copyTextureToBuffer( dstSize, dstRowStride, getInnerObj(src), - srcState, srcSubresource, srcOffset, extent diff --git a/src/debug-layer/debug-command-encoder.h b/src/debug-layer/debug-command-encoder.h index 9928e78..360bf41 100644 --- a/src/debug-layer/debug-command-encoder.h +++ b/src/debug-layer/debug-command-encoder.h @@ -24,18 +24,10 @@ class DebugCommandEncoder : public ICommandEncoder uint32_t addRef() override { return 2; } uint32_t release() override { return 2; } - virtual SLANG_NO_THROW void SLANG_MCALL - textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) override; - - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst - ) override; + virtual SLANG_NO_THROW void SLANG_MCALL setBufferState(IBuffer* buffer, ResourceState state) override; virtual SLANG_NO_THROW void SLANG_MCALL - bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) override; + setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) override; virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) override; virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override; @@ -76,11 +68,9 @@ class DebugResourceCommandEncoder : public UnownedDebugObjectreadTexture(getInnerObj(resource), state, outBlob, outRowPitch, outPixelSize); + return baseObject->readTexture(getInnerObj(texture), outBlob, outRowPitch, outPixelSize); } Result DebugDevice::readBuffer(IBuffer* buffer, size_t offset, size_t size, ISlangBlob** outBlob) diff --git a/src/debug-layer/debug-device.h b/src/debug-layer/debug-device.h index 7f32737..4c798cb 100644 --- a/src/debug-layer/debug-device.h +++ b/src/debug-layer/debug-device.h @@ -98,8 +98,7 @@ class DebugDevice : public DebugObject virtual SLANG_NO_THROW Result SLANG_MCALL createRayTracingPipeline(const RayTracingPipelineDesc& desc, IPipeline** outPipeline) override; virtual SLANG_NO_THROW Result SLANG_MCALL - readTexture(ITexture* resource, ResourceState state, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) - override; + readTexture(ITexture* texture, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) override; virtual SLANG_NO_THROW Result SLANG_MCALL readBuffer(IBuffer* buffer, Offset offset, Size size, ISlangBlob** outBlob) override; virtual SLANG_NO_THROW const DeviceInfo& SLANG_MCALL getDeviceInfo() const override; diff --git a/src/enum-strings.cpp b/src/enum-strings.cpp index 694373e..14fcb6d 100644 --- a/src/enum-strings.cpp +++ b/src/enum-strings.cpp @@ -199,8 +199,6 @@ const char* enumToString(ResourceState value) return "Undefined"; case ResourceState::General: return "General"; - case ResourceState::PreInitialized: - return "PreInitialized"; case ResourceState::VertexBuffer: return "VertexBuffer"; case ResourceState::IndexBuffer: @@ -235,10 +233,6 @@ const char* enumToString(ResourceState value) return "AccelerationStructure"; case ResourceState::AccelerationStructureBuildInput: return "AccelerationStructureBuildInput"; - case ResourceState::PixelShaderResource: - return "PixelShaderResource"; - case ResourceState::NonPixelShaderResource: - return "NonPixelShaderResource"; } return kInvalid; } diff --git a/src/immediate-device.cpp b/src/immediate-device.cpp index e0ae2da..d2389eb 100644 --- a/src/immediate-device.cpp +++ b/src/immediate-device.cpp @@ -69,35 +69,18 @@ class CommandBufferImpl : public ICommandBuffer, public ComObject virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() override { return 1; } virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; } - virtual SLANG_NO_THROW void SLANG_MCALL - textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) override + virtual SLANG_NO_THROW void SLANG_MCALL setBufferState(IBuffer* buffer, ResourceState state) override { - SLANG_UNUSED(count); - SLANG_UNUSED(textures); - SLANG_UNUSED(src); - SLANG_UNUSED(dst); + SLANG_UNUSED(buffer); + SLANG_UNUSED(state); } - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst - ) override + virtual SLANG_NO_THROW void SLANG_MCALL + setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) override { SLANG_UNUSED(texture); SLANG_UNUSED(subresourceRange); - SLANG_UNUSED(src); - SLANG_UNUSED(dst); - } - - virtual SLANG_NO_THROW void SLANG_MCALL - bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) override - { - SLANG_UNUSED(count); - SLANG_UNUSED(buffers); - SLANG_UNUSED(src); - SLANG_UNUSED(dst); + SLANG_UNUSED(state); } virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) override @@ -145,22 +128,18 @@ class CommandBufferImpl : public ICommandBuffer, public ComObject virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( ITexture* dst, - ResourceState dstState, SubresourceRange dstSubresource, Offset3D dstOffset, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent ) override { SLANG_UNUSED(dst); - SLANG_UNUSED(dstState); SLANG_UNUSED(dstSubresource); SLANG_UNUSED(dstOffset); SLANG_UNUSED(src); - SLANG_UNUSED(srcState); SLANG_UNUSED(srcSubresource); SLANG_UNUSED(srcOffset); SLANG_UNUSED(extent); @@ -208,24 +187,6 @@ class CommandBufferImpl : public ICommandBuffer, public ComObject SLANG_RHI_UNIMPLEMENTED("clearTexture"); } - virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( - ITexture* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITexture* dest, - ResourceState destState, - SubresourceRange destRange - ) override - { - SLANG_UNUSED(source); - SLANG_UNUSED(sourceState); - SLANG_UNUSED(sourceRange); - SLANG_UNUSED(dest); - SLANG_UNUSED(destState); - SLANG_UNUSED(destRange); - SLANG_RHI_UNIMPLEMENTED("resolveResource"); - } - virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery(IQueryPool* queryPool, GfxIndex index, GfxCount count, IBuffer* buffer, Offset offset) override { @@ -243,7 +204,6 @@ class CommandBufferImpl : public ICommandBuffer, public ComObject Size dstSize, Size dstRowStride, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -254,7 +214,6 @@ class CommandBufferImpl : public ICommandBuffer, public ComObject SLANG_UNUSED(dstSize); SLANG_UNUSED(dstRowStride); SLANG_UNUSED(src); - SLANG_UNUSED(srcState); SLANG_UNUSED(srcSubresource); SLANG_UNUSED(srcOffset); SLANG_UNUSED(extent); diff --git a/src/immediate-device.h b/src/immediate-device.h index b121249..632dadf 100644 --- a/src/immediate-device.h +++ b/src/immediate-device.h @@ -201,8 +201,7 @@ class ImmediateComputeDeviceBase : public ImmediateDevice return SLANG_E_NOT_AVAILABLE; } virtual SLANG_NO_THROW Result SLANG_MCALL - readTexture(ITexture* texture, ResourceState state, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) - override + readTexture(ITexture* texture, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) override { SLANG_UNUSED(texture); SLANG_UNUSED(outBlob); diff --git a/src/metal/metal-command-encoder.cpp b/src/metal/metal-command-encoder.cpp index 10f0e41..21297d5 100644 --- a/src/metal/metal-command-encoder.cpp +++ b/src/metal/metal-command-encoder.cpp @@ -14,22 +14,12 @@ namespace rhi::metal { // CommandEncoderImpl -void CommandEncoderImpl::textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) +void CommandEncoderImpl::setBufferState(IBuffer* buffer, ResourceState state) { // We use automatic hazard tracking for now, no need for barriers. } -void CommandEncoderImpl::textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst -) -{ - // We use automatic hazard tracking for now, no need for barriers. -} - -void CommandEncoderImpl::bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) +void CommandEncoderImpl::setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) { // We use automatic hazard tracking for now, no need for barriers. } @@ -96,11 +86,9 @@ void ResourceCommandEncoderImpl::copyBuffer(IBuffer* dst, Offset dstOffset, IBuf void ResourceCommandEncoderImpl::copyTexture( ITexture* dst, - ResourceState dstState, SubresourceRange dstSubresource, Offset3D dstOffset, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -141,7 +129,6 @@ void ResourceCommandEncoderImpl::copyTextureToBuffer( Size dstSize, Size dstRowStride, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -196,18 +183,6 @@ void ResourceCommandEncoderImpl::clearTexture( SLANG_RHI_UNIMPLEMENTED("clearTexture"); } -void ResourceCommandEncoderImpl::resolveResource( - ITexture* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITexture* dest, - ResourceState destState, - SubresourceRange destRange -) -{ - SLANG_RHI_UNIMPLEMENTED("resolveResource"); -} - void ResourceCommandEncoderImpl::resolveQuery( IQueryPool* queryPool, GfxIndex index, @@ -268,6 +243,10 @@ Result RenderCommandEncoderImpl::beginPass(const RenderPassDesc& desc) )); } colorAttachment->setTexture(view->m_textureView.get()); + colorAttachment->setResolveTexture( + attachment.resolveTarget ? static_cast(attachment.resolveTarget)->m_textureView.get() + : nullptr + ); colorAttachment->setLevel(view->m_desc.subresourceRange.mipLevel); colorAttachment->setSlice(view->m_desc.subresourceRange.baseArrayLayer); } diff --git a/src/metal/metal-command-encoder.h b/src/metal/metal-command-encoder.h index 8c10766..5bc704f 100644 --- a/src/metal/metal-command-encoder.h +++ b/src/metal/metal-command-encoder.h @@ -29,16 +29,9 @@ class CommandEncoderImpl : public ICommandEncoder virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; } public: + virtual SLANG_NO_THROW void SLANG_MCALL setBufferState(IBuffer* buffer, ResourceState state) override; virtual SLANG_NO_THROW void SLANG_MCALL - textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) override; - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst - ) override; - virtual SLANG_NO_THROW void SLANG_MCALL - bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) override; + setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) override; virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) override; virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override; @@ -78,11 +71,9 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( ITexture* dst, - ResourceState dstState, SubresourceRange dstSubresource, Offset3D dstOffset, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -94,7 +85,6 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman Size dstSize, Size dstRowStride, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -122,15 +112,6 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman bool clearStencil ) override; - virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( - ITexture* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITexture* dest, - ResourceState destState, - SubresourceRange destRange - ) override; - virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery(IQueryPool* queryPool, GfxIndex index, GfxCount count, IBuffer* buffer, Offset offset) override; }; diff --git a/src/metal/metal-device.cpp b/src/metal/metal-device.cpp index 439e3a3..eab90e5 100644 --- a/src/metal/metal-device.cpp +++ b/src/metal/metal-device.cpp @@ -146,13 +146,7 @@ Result DeviceImpl::createSwapchain(const ISwapchain::Desc& desc, WindowHandle wi return SLANG_OK; } -Result DeviceImpl::readTexture( - ITexture* texture, - ResourceState state, - ISlangBlob** outBlob, - Size* outRowPitch, - Size* outPixelSize -) +Result DeviceImpl::readTexture(ITexture* texture, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) { AUTORELEASEPOOL diff --git a/src/metal/metal-device.h b/src/metal/metal-device.h index 2728373..0449050 100644 --- a/src/metal/metal-device.h +++ b/src/metal/metal-device.h @@ -61,8 +61,7 @@ class DeviceImpl : public Device virtual SLANG_NO_THROW Result SLANG_MCALL createQueryPool(const QueryPoolDesc& desc, IQueryPool** outPool) override; virtual SLANG_NO_THROW Result SLANG_MCALL - readTexture(ITexture* texture, ResourceState state, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) - override; + readTexture(ITexture* texture, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) override; virtual SLANG_NO_THROW Result SLANG_MCALL readBuffer(IBuffer* buffer, Offset offset, Size size, ISlangBlob** outBlob) override; diff --git a/src/rhi-shared.cpp b/src/rhi-shared.cpp index 5550799..c9113a0 100644 --- a/src/rhi-shared.cpp +++ b/src/rhi-shared.cpp @@ -119,6 +119,20 @@ SubresourceRange Texture::resolveSubresourceRange(const SubresourceRange& range) return resolved; } +bool Texture::isEntireTexture(const SubresourceRange& range) +{ + if (range.mipLevel > 0 || range.mipLevelCount < m_desc.numMipLevels) + { + return false; + } + GfxCount arrayLayerCount = m_desc.arrayLength * (m_desc.type == TextureType::TextureCube ? 6 : 1); + if (range.baseArrayLayer > 0 || range.layerCount < arrayLayerCount) + { + return false; + } + return true; +} + ITextureView* TextureView::getInterface(const Guid& guid) { if (guid == GUID::IID_ISlangUnknown || guid == GUID::IID_IResource || guid == GUID::IID_ITextureView) diff --git a/src/rhi-shared.h b/src/rhi-shared.h index 6044ca9..ae4d2c1 100644 --- a/src/rhi-shared.h +++ b/src/rhi-shared.h @@ -246,6 +246,7 @@ class Texture : public ITexture, public Resource virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(NativeHandle* outHandle) SLANG_OVERRIDE; SubresourceRange resolveSubresourceRange(const SubresourceRange& range); + bool isEntireTexture(const SubresourceRange& range); public: TextureDesc m_desc; diff --git a/src/state-tracking.h b/src/state-tracking.h new file mode 100644 index 0000000..37cbe91 --- /dev/null +++ b/src/state-tracking.h @@ -0,0 +1,194 @@ +#pragma once + +#include "rhi-shared.h" + +#include +#include + +namespace rhi { + +struct BufferState +{ + ResourceState state = ResourceState::Undefined; +}; + +struct TextureState +{ + ResourceState state = ResourceState::Undefined; + std::vector subresourceStates; +}; + +struct BufferBarrier +{ + Buffer* buffer; + ResourceState stateBefore; + ResourceState stateAfter; +}; + +struct TextureBarrier +{ + Texture* texture; + bool entireTexture; + GfxIndex mipLevel; + GfxIndex arrayLayer; + ResourceState stateBefore; + ResourceState stateAfter; +}; + +class StateTracking +{ +public: + void setBufferState(Buffer* buffer, ResourceState state) + { + // Cannot change state of upload/readback buffers. + if (buffer->m_desc.memoryType != MemoryType::DeviceLocal) + { + return; + } + + BufferState* bufferState = getBufferState(buffer); + if (state != bufferState->state || state == ResourceState::UnorderedAccess) + { + m_bufferBarriers.push_back({buffer, bufferState->state, state}); + bufferState->state = state; + } + } + + void setTextureState(Texture* texture, SubresourceRange subresourceRange, ResourceState state) + { + // Cannot change state of upload/readback buffers. + if (texture->m_desc.memoryType != MemoryType::DeviceLocal) + { + return; + } + + subresourceRange = texture->resolveSubresourceRange(subresourceRange); + bool isEntireTexture = texture->isEntireTexture(subresourceRange); + TextureState* textureState = getTextureState(texture); + + if (isEntireTexture && textureState->subresourceStates.empty()) + { + // Transition entire texture. + if (state != textureState->state || state == ResourceState::UnorderedAccess) + { + m_textureBarriers.push_back({texture, true, 0, 0, textureState->state, state}); + textureState->state = state; + } + } + else + { + // Transition subresources. + GfxCount arrayLayerCount = + texture->m_desc.arrayLength * (texture->m_desc.type == TextureType::TextureCube ? 6 : 1); + + if (textureState->subresourceStates.empty()) + { + textureState->subresourceStates.resize( + texture->m_desc.numMipLevels * arrayLayerCount, + textureState->state + ); + textureState->state = ResourceState::Undefined; + } + for (GfxIndex arrayLayer = subresourceRange.baseArrayLayer; arrayLayer < arrayLayerCount; arrayLayer++) + { + for (GfxIndex mipLevel = subresourceRange.mipLevel; + mipLevel < subresourceRange.mipLevel + subresourceRange.mipLevelCount; + mipLevel++) + { + GfxIndex subresourceIndex = arrayLayer * texture->m_desc.numMipLevels + mipLevel; + if (state != textureState->subresourceStates[subresourceIndex] || + state == ResourceState::UnorderedAccess) + { + m_textureBarriers.push_back({ + texture, + false, + mipLevel, + arrayLayer, + textureState->subresourceStates[subresourceIndex], + state, + }); + textureState->subresourceStates[subresourceIndex] = state; + } + } + } + + // Check if all subresource states are equal and we can represent them as a single texture state. + ResourceState commonState = textureState->subresourceStates[0]; + bool allEqual = true; + for (ResourceState subresourceState : textureState->subresourceStates) + { + if (subresourceState != commonState) + { + allEqual = false; + break; + } + } + if (allEqual) + { + textureState->state = commonState; + textureState->subresourceStates.clear(); + } + } + } + + void requireDefaultStates() + { + for (auto& bufferState : m_bufferStates) + { + if (bufferState.second.state != bufferState.first->m_desc.defaultState) + { + setBufferState(bufferState.first, bufferState.first->m_desc.defaultState); + } + } + for (auto& textureState : m_textureStates) + { + if (textureState.second.state != textureState.first->m_desc.defaultState) + { + setTextureState(textureState.first, kEntireTexture, textureState.first->m_desc.defaultState); + } + } + } + + const std::vector& getBufferBarriers() const { return m_bufferBarriers; } + + const std::vector& getTextureBarriers() const { return m_textureBarriers; } + + void clearBarriers() + { + m_bufferBarriers.clear(); + m_textureBarriers.clear(); + } + + void clear() + { + m_bufferStates.clear(); + m_textureStates.clear(); + clearBarriers(); + } + +private: + std::map m_bufferStates; + std::map m_textureStates; + std::vector m_bufferBarriers; + std::vector m_textureBarriers; + + BufferState* getBufferState(Buffer* buffer) + { + auto it = m_bufferStates.find(buffer); + if (it != m_bufferStates.end()) + return &it->second; + m_bufferStates[buffer] = {buffer->m_desc.defaultState}; + return &m_bufferStates[buffer]; + } + + TextureState* getTextureState(Texture* texture) + { + auto it = m_textureStates.find(texture); + if (it != m_textureStates.end()) + return &it->second; + m_textureStates[texture] = {texture->m_desc.defaultState}; + return &m_textureStates[texture]; + } +}; + +} // namespace rhi diff --git a/src/vulkan/vk-command-buffer.cpp b/src/vulkan/vk-command-buffer.cpp index aa177c9..8a91ad1 100644 --- a/src/vulkan/vk-command-buffer.cpp +++ b/src/vulkan/vk-command-buffer.cpp @@ -76,6 +76,136 @@ VkCommandBuffer CommandBufferImpl::getPreCommandBuffer() return m_preCommandBuffer; } +void CommandBufferImpl::requireBufferState(BufferImpl* buffer, ResourceState state) +{ + m_stateTracking.setBufferState(buffer, state); +} + +void CommandBufferImpl::requireTextureState( + TextureImpl* texture, + SubresourceRange subresourceRange, + ResourceState state +) +{ + m_stateTracking.setTextureState(texture, subresourceRange, state); +} + +void CommandBufferImpl::commitBarriers() +{ + auto& api = m_device->m_api; + + short_vector bufferBarriers; + short_vector imageBarriers; + + VkPipelineStageFlags activeBeforeStageFlags = VkPipelineStageFlags(0); + VkPipelineStageFlags activeAfterStageFlags = VkPipelineStageFlags(0); + + auto submitBufferBarriers = [&]() + { + api.vkCmdPipelineBarrier( + m_commandBuffer, + activeBeforeStageFlags, + activeAfterStageFlags, + VkDependencyFlags(0), + 0, + nullptr, + (uint32_t)bufferBarriers.size(), + bufferBarriers.data(), + 0, + nullptr + ); + }; + + auto submitImageBarriers = [&]() + { + api.vkCmdPipelineBarrier( + m_commandBuffer, + activeBeforeStageFlags, + activeAfterStageFlags, + VkDependencyFlags(0), + 0, + nullptr, + 0, + nullptr, + (uint32_t)imageBarriers.size(), + imageBarriers.data() + ); + }; + + for (const auto& bufferBarrier : m_stateTracking.getBufferBarriers()) + { + BufferImpl* buffer = static_cast(bufferBarrier.buffer); + + VkPipelineStageFlags beforeStageFlags = calcPipelineStageFlags(bufferBarrier.stateBefore, true); + VkPipelineStageFlags afterStageFlags = calcPipelineStageFlags(bufferBarrier.stateAfter, false); + + if ((beforeStageFlags != activeBeforeStageFlags || afterStageFlags != activeAfterStageFlags) && + !bufferBarriers.empty()) + { + submitBufferBarriers(); + bufferBarriers.clear(); + } + + activeBeforeStageFlags = beforeStageFlags; + activeAfterStageFlags = afterStageFlags; + + VkBufferMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.srcAccessMask = calcAccessFlags(bufferBarrier.stateBefore); + barrier.dstAccessMask = calcAccessFlags(bufferBarrier.stateAfter); + barrier.buffer = buffer->m_buffer.m_buffer; + barrier.offset = 0; + barrier.size = buffer->m_desc.size; + + bufferBarriers.push_back(barrier); + } + if (!bufferBarriers.empty()) + { + submitBufferBarriers(); + } + + activeBeforeStageFlags = VkPipelineStageFlags(0); + activeAfterStageFlags = VkPipelineStageFlags(0); + + for (const auto& textureBarrier : m_stateTracking.getTextureBarriers()) + { + TextureImpl* texture = static_cast(textureBarrier.texture); + + VkPipelineStageFlags beforeStageFlags = calcPipelineStageFlags(textureBarrier.stateBefore, true); + VkPipelineStageFlags afterStageFlags = calcPipelineStageFlags(textureBarrier.stateAfter, false); + + if ((beforeStageFlags != activeBeforeStageFlags || afterStageFlags != activeAfterStageFlags) && + !imageBarriers.empty()) + { + submitImageBarriers(); + imageBarriers.clear(); + } + + activeBeforeStageFlags = beforeStageFlags; + activeAfterStageFlags = afterStageFlags; + + VkImageMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.image = texture->m_image; + barrier.oldLayout = translateImageLayout(textureBarrier.stateBefore); + barrier.newLayout = translateImageLayout(textureBarrier.stateAfter); + barrier.subresourceRange.aspectMask = getAspectMaskFromFormat(VulkanUtil::getVkFormat(texture->m_desc.format)); + barrier.subresourceRange.baseArrayLayer = textureBarrier.entireTexture ? 0 : textureBarrier.arrayLayer; + barrier.subresourceRange.baseMipLevel = textureBarrier.entireTexture ? 0 : textureBarrier.mipLevel; + barrier.subresourceRange.layerCount = textureBarrier.entireTexture ? VK_REMAINING_ARRAY_LAYERS : 1; + barrier.subresourceRange.levelCount = textureBarrier.entireTexture ? VK_REMAINING_MIP_LEVELS : 1; + barrier.srcAccessMask = calcAccessFlags(textureBarrier.stateBefore); + barrier.dstAccessMask = calcAccessFlags(textureBarrier.stateAfter); + imageBarriers.push_back(barrier); + } + if (!imageBarriers.empty()) + { + submitImageBarriers(); + } + + m_stateTracking.clearBarriers(); +} + Result CommandBufferImpl::encodeResourceCommands(IResourceCommandEncoder** outEncoder) { m_resourceCommandEncoder.init(this); diff --git a/src/vulkan/vk-command-buffer.h b/src/vulkan/vk-command-buffer.h index 523194b..5c89dd1 100644 --- a/src/vulkan/vk-command-buffer.h +++ b/src/vulkan/vk-command-buffer.h @@ -5,6 +5,8 @@ #include "vk-shader-object.h" #include "vk-transient-heap.h" +#include "../state-tracking.h" + namespace rhi::vk { class CommandBufferImpl : public ICommandBuffer, public ComObject @@ -27,6 +29,8 @@ class CommandBufferImpl : public ICommandBuffer, public ComObject RootShaderObjectImpl m_rootObject; RefPtr m_mutableRootShaderObject; + StateTracking m_stateTracking; + ResourceCommandEncoderImpl m_resourceCommandEncoder; RenderCommandEncoderImpl m_renderCommandEncoder; ComputeCommandEncoderImpl m_computeCommandEncoder; @@ -44,6 +48,10 @@ class CommandBufferImpl : public ICommandBuffer, public ComObject VkCommandBuffer getPreCommandBuffer(); + void requireBufferState(BufferImpl* buffer, ResourceState state); + void requireTextureState(TextureImpl* texture, SubresourceRange subresourceRange, ResourceState state); + void commitBarriers(); + public: virtual SLANG_NO_THROW Result SLANG_MCALL encodeResourceCommands(IResourceCommandEncoder** outEncoder) override; virtual SLANG_NO_THROW Result SLANG_MCALL diff --git a/src/vulkan/vk-command-encoder.cpp b/src/vulkan/vk-command-encoder.cpp index 4127a0f..0964c6a 100644 --- a/src/vulkan/vk-command-encoder.cpp +++ b/src/vulkan/vk-command-encoder.cpp @@ -20,128 +20,14 @@ namespace rhi::vk { // CommandEncoderImpl -void CommandEncoderImpl::textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) +void CommandEncoderImpl::setBufferState(IBuffer* buffer, ResourceState state) { - short_vector barriers; - - for (GfxIndex i = 0; i < count; i++) - { - TextureImpl* texture = static_cast(textures[i]); - const TextureDesc& desc = texture->getDesc(); - - VkImageMemoryBarrier barrier = {}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.image = texture->m_image; - barrier.oldLayout = translateImageLayout(src); - barrier.newLayout = translateImageLayout(dst); - barrier.subresourceRange.aspectMask = getAspectMaskFromFormat(VulkanUtil::getVkFormat(desc.format)); - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.srcAccessMask = calcAccessFlags(src); - barrier.dstAccessMask = calcAccessFlags(dst); - barriers.push_back(barrier); - } - - VkPipelineStageFlagBits srcStage = calcPipelineStageFlags(src, true); - VkPipelineStageFlagBits dstStage = calcPipelineStageFlags(dst, false); - - auto& api = m_commandBuffer->m_device->m_api; - api.vkCmdPipelineBarrier( - m_commandBuffer->m_commandBuffer, - srcStage, - dstStage, - 0, - 0, - nullptr, - 0, - nullptr, - (uint32_t)count, - barriers.data() - ); -} - -void CommandEncoderImpl::textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst -) -{ - short_vector barriers; - auto image = static_cast(texture); - auto desc = image->getDesc(); - - VkImageMemoryBarrier barrier = {}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.image = image->m_image; - barrier.oldLayout = translateImageLayout(src); - barrier.newLayout = translateImageLayout(dst); - barrier.subresourceRange.aspectMask = VulkanUtil::getAspectMask(subresourceRange.aspectMask, image->m_vkformat); - barrier.subresourceRange.baseArrayLayer = subresourceRange.baseArrayLayer; - barrier.subresourceRange.baseMipLevel = subresourceRange.mipLevel; - barrier.subresourceRange.layerCount = subresourceRange.layerCount; - barrier.subresourceRange.levelCount = subresourceRange.mipLevelCount; - barrier.srcAccessMask = calcAccessFlags(src); - barrier.dstAccessMask = calcAccessFlags(dst); - barriers.push_back(barrier); - - VkPipelineStageFlagBits srcStage = calcPipelineStageFlags(src, true); - VkPipelineStageFlagBits dstStage = calcPipelineStageFlags(dst, false); - - auto& api = m_commandBuffer->m_device->m_api; - api.vkCmdPipelineBarrier( - m_commandBuffer->m_commandBuffer, - srcStage, - dstStage, - 0, - 0, - nullptr, - 0, - nullptr, - (uint32_t)barriers.size(), - barriers.data() - ); + m_commandBuffer->m_stateTracking.setBufferState(static_cast(buffer), state); } -// TODO: Change size_t to Count? -void CommandEncoderImpl::bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) +void CommandEncoderImpl::setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) { - std::vector barriers; - barriers.reserve(count); - - for (GfxIndex i = 0; i < count; i++) - { - BufferImpl* buffer = static_cast(buffers[i]); - - VkBufferMemoryBarrier barrier = {}; - barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - barrier.srcAccessMask = calcAccessFlags(src); - barrier.dstAccessMask = calcAccessFlags(dst); - barrier.buffer = buffer->m_buffer.m_buffer; - barrier.offset = 0; - barrier.size = buffer->m_desc.size; - - barriers.push_back(barrier); - } - - VkPipelineStageFlagBits srcStage = calcPipelineStageFlags(src, true); - VkPipelineStageFlagBits dstStage = calcPipelineStageFlags(dst, false); - - auto& api = m_commandBuffer->m_device->m_api; - api.vkCmdPipelineBarrier( - m_commandBuffer->m_commandBuffer, - srcStage, - dstStage, - 0, - 0, - nullptr, - (uint32_t)barriers.size(), - barriers.data(), - 0, - nullptr - ); + m_commandBuffer->m_stateTracking.setTextureState(static_cast(texture), subresourceRange, state); } void CommandEncoderImpl::beginDebugEvent(const char* name, float rgbColor[3]) @@ -282,6 +168,9 @@ Result CommandEncoderImpl::bindRootShaderObjectImpl( context.descriptorSets = &descriptorSetsStorage; + rootShaderObject->setResourceStates(m_commandBuffer->m_stateTracking); + m_commandBuffer->commitBarriers(); + // We kick off recursive binding of shader objects to the pipeline (plus // the state in `context`). // @@ -366,8 +255,12 @@ void ResourceCommandEncoderImpl::copyBuffer(IBuffer* dst, Offset dstOffset, IBuf { auto& vkAPI = m_commandBuffer->m_device->m_api; - auto dstBuffer = static_cast(dst); - auto srcBuffer = static_cast(src); + BufferImpl* dstBuffer = static_cast(dst); + BufferImpl* srcBuffer = static_cast(src); + + m_commandBuffer->requireBufferState(dstBuffer, ResourceState::CopyDestination); + m_commandBuffer->requireBufferState(srcBuffer, ResourceState::CopySource); + m_commandBuffer->commitBarriers(); VkBufferCopy copyRegion; copyRegion.dstOffset = dstOffset; @@ -389,11 +282,16 @@ void ResourceCommandEncoderImpl::copyBuffer(IBuffer* dst, Offset dstOffset, IBuf void ResourceCommandEncoderImpl::uploadBufferData(IBuffer* buffer, Offset offset, Size size, void* data) { + BufferImpl* bufferImpl = static_cast(buffer); + + m_commandBuffer->requireBufferState(bufferImpl, ResourceState::CopyDestination); + m_commandBuffer->commitBarriers(); + CommandEncoderImpl::_uploadBufferData( m_api, m_commandBuffer->m_commandBuffer, m_commandBuffer->m_transientHeap.get(), - static_cast(buffer), + bufferImpl, offset, size, data @@ -425,22 +323,25 @@ void ResourceCommandEncoderImpl::endEncoding() void ResourceCommandEncoderImpl::copyTexture( ITexture* dst, - ResourceState dstState, SubresourceRange dstSubresource, Offset3D dstOffset, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent ) { - TextureImpl* srcImage = static_cast(src); - const TextureDesc& srcDesc = srcImage->m_desc; - VkImageLayout srcImageLayout = VulkanUtil::getImageLayoutFromState(srcState); - TextureImpl* dstImage = static_cast(dst); - const TextureDesc& dstDesc = dstImage->m_desc; - VkImageLayout dstImageLayout = VulkanUtil::getImageLayoutFromState(dstState); + TextureImpl* dstTexture = static_cast(dst); + TextureImpl* srcTexture = static_cast(src); + + m_commandBuffer->requireTextureState(dstTexture, dstSubresource, ResourceState::CopyDestination); + m_commandBuffer->requireTextureState(srcTexture, srcSubresource, ResourceState::CopySource); + m_commandBuffer->commitBarriers(); + + const TextureDesc& srcDesc = srcTexture->m_desc; + VkImageLayout srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + const TextureDesc& dstDesc = dstTexture->m_desc; + VkImageLayout dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; if (dstSubresource.layerCount == 0 && dstSubresource.mipLevelCount == 0) { extent = dstDesc.size; @@ -458,12 +359,12 @@ void ResourceCommandEncoderImpl::copyTexture( srcSubresource.mipLevelCount = dstDesc.numMipLevels; } VkImageCopy region = {}; - region.srcSubresource.aspectMask = VulkanUtil::getAspectMask(srcSubresource.aspectMask, srcImage->m_vkformat); + region.srcSubresource.aspectMask = VulkanUtil::getAspectMask(srcSubresource.aspectMask, srcTexture->m_vkformat); region.srcSubresource.baseArrayLayer = srcSubresource.baseArrayLayer; region.srcSubresource.mipLevel = srcSubresource.mipLevel; region.srcSubresource.layerCount = srcSubresource.layerCount; region.srcOffset = {(int32_t)srcOffset.x, (int32_t)srcOffset.y, (int32_t)srcOffset.z}; - region.dstSubresource.aspectMask = VulkanUtil::getAspectMask(dstSubresource.aspectMask, dstImage->m_vkformat); + region.dstSubresource.aspectMask = VulkanUtil::getAspectMask(dstSubresource.aspectMask, dstTexture->m_vkformat); region.dstSubresource.baseArrayLayer = dstSubresource.baseArrayLayer; region.dstSubresource.mipLevel = dstSubresource.mipLevel; region.dstSubresource.layerCount = dstSubresource.layerCount; @@ -473,9 +374,9 @@ void ResourceCommandEncoderImpl::copyTexture( auto& api = m_commandBuffer->m_device->m_api; api.vkCmdCopyImage( m_commandBuffer->m_commandBuffer, - srcImage->m_image, + srcTexture->m_image, srcImageLayout, - dstImage->m_image, + dstTexture->m_image, dstImageLayout, 1, ®ion @@ -491,14 +392,16 @@ void ResourceCommandEncoderImpl::uploadTextureData( GfxCount subResourceDataCount ) { - // VALIDATION: dst must be in TransferDst state. + TextureImpl* dstTexture = static_cast(dst); + + m_commandBuffer->requireTextureState(dstTexture, subResourceRange, ResourceState::CopyDestination); + m_commandBuffer->commitBarriers(); auto& api = m_commandBuffer->m_device->m_api; - auto dstImpl = static_cast(dst); std::vector mipSizes; VkCommandBuffer commandBuffer = m_commandBuffer->m_commandBuffer; - const TextureDesc& desc = dstImpl->m_desc; + const TextureDesc& desc = dstTexture->m_desc; // Calculate how large the buffer has to be Size bufferSize = 0; // Calculate how large an array entry is @@ -598,7 +501,7 @@ void ResourceCommandEncoderImpl::uploadTextureData( region.bufferRowLength = 0; // rowSizeInBytes; region.bufferImageHeight = 0; - region.imageSubresource.aspectMask = getAspectMaskFromFormat(dstImpl->m_vkformat); + region.imageSubresource.aspectMask = getAspectMaskFromFormat(dstTexture->m_vkformat); region.imageSubresource.mipLevel = subResourceRange.mipLevel + uint32_t(j); region.imageSubresource.baseArrayLayer = subResourceRange.baseArrayLayer + i; region.imageSubresource.layerCount = 1; @@ -609,7 +512,7 @@ void ResourceCommandEncoderImpl::uploadTextureData( api.vkCmdCopyBufferToImage( commandBuffer, static_cast(uploadBuffer)->m_buffer.m_buffer, - dstImpl->m_image, + dstTexture->m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion @@ -837,9 +740,12 @@ void ResourceCommandEncoderImpl::clearResourceView( void ResourceCommandEncoderImpl::clearBuffer(IBuffer* buffer, const BufferRange* range) { - // TODO(skallweit) transition to copy destination - auto& api = m_commandBuffer->m_device->m_api; BufferImpl* bufferImpl = static_cast(buffer); + + m_commandBuffer->requireBufferState(bufferImpl, ResourceState::CopyDestination); + m_commandBuffer->commitBarriers(); + + auto& api = m_commandBuffer->m_device->m_api; uint64_t offset = range ? range->offset : 0; uint64_t size = range ? range->size : bufferImpl->m_desc.size; api.vkCmdFillBuffer(m_commandBuffer->m_commandBuffer, bufferImpl->m_buffer.m_buffer, offset, size, 0); @@ -856,57 +762,6 @@ void ResourceCommandEncoderImpl::clearTexture( SLANG_RHI_UNIMPLEMENTED("clearTexture"); } -void ResourceCommandEncoderImpl::resolveResource( - ITexture* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITexture* dest, - ResourceState destState, - SubresourceRange destRange -) -{ - TextureImpl* srcTexture = static_cast(source); - auto srcExtent = srcTexture->m_desc.size; - auto dstTexture = static_cast(dest); - - auto srcImage = srcTexture->m_image; - auto dstImage = dstTexture->m_image; - - auto srcImageLayout = VulkanUtil::getImageLayoutFromState(sourceState); - auto dstImageLayout = VulkanUtil::getImageLayoutFromState(destState); - - for (GfxIndex layer = 0; layer < sourceRange.layerCount; ++layer) - { - for (GfxIndex mip = 0; mip < sourceRange.mipLevelCount; ++mip) - { - VkImageResolve region = {}; - region.srcSubresource.aspectMask = - VulkanUtil::getAspectMask(sourceRange.aspectMask, srcTexture->m_vkformat); - region.srcSubresource.baseArrayLayer = layer + sourceRange.baseArrayLayer; - region.srcSubresource.layerCount = 1; - region.srcSubresource.mipLevel = mip + sourceRange.mipLevel; - region.srcOffset = {0, 0, 0}; - region.dstSubresource.aspectMask = VulkanUtil::getAspectMask(destRange.aspectMask, dstTexture->m_vkformat); - region.dstSubresource.baseArrayLayer = layer + destRange.baseArrayLayer; - region.dstSubresource.layerCount = 1; - region.dstSubresource.mipLevel = mip + destRange.mipLevel; - region.dstOffset = {0, 0, 0}; - region.extent = {(uint32_t)srcExtent.width, (uint32_t)srcExtent.height, (uint32_t)srcExtent.depth}; - - auto& api = m_commandBuffer->m_device->m_api; - api.vkCmdResolveImage( - m_commandBuffer->m_commandBuffer, - srcImage, - srcImageLayout, - dstImage, - dstImageLayout, - 1, - ®ion - ); - } - } -} - void ResourceCommandEncoderImpl::resolveQuery( IQueryPool* queryPool, GfxIndex index, @@ -915,9 +770,13 @@ void ResourceCommandEncoderImpl::resolveQuery( Offset offset ) { + QueryPoolImpl* poolImpl = static_cast(queryPool); + BufferImpl* bufferImpl = static_cast(buffer); + + m_commandBuffer->requireBufferState(bufferImpl, ResourceState::CopyDestination); + m_commandBuffer->commitBarriers(); + auto& api = m_commandBuffer->m_device->m_api; - auto poolImpl = static_cast(queryPool); - auto bufferImpl = static_cast(buffer); api.vkCmdCopyQueryPoolResults( m_commandBuffer->m_commandBuffer, poolImpl->m_pool, @@ -936,7 +795,6 @@ void ResourceCommandEncoderImpl::copyTextureToBuffer( Size dstSize, Size dstRowStride, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -944,16 +802,18 @@ void ResourceCommandEncoderImpl::copyTextureToBuffer( { SLANG_RHI_ASSERT(srcSubresource.mipLevelCount <= 1); - auto image = static_cast(src); - auto desc = image->getDesc(); - auto buffer = static_cast(dst); - auto srcImageLayout = VulkanUtil::getImageLayoutFromState(srcState); + BufferImpl* dstBuffer = static_cast(dst); + TextureImpl* srcTexture = static_cast(src); + + m_commandBuffer->requireBufferState(dstBuffer, ResourceState::CopyDestination); + m_commandBuffer->requireTextureState(srcTexture, srcSubresource, ResourceState::CopySource); + m_commandBuffer->commitBarriers(); VkBufferImageCopy region = {}; region.bufferOffset = dstOffset; region.bufferRowLength = 0; region.bufferImageHeight = 0; - region.imageSubresource.aspectMask = VulkanUtil::getAspectMask(srcSubresource.aspectMask, image->m_vkformat); + region.imageSubresource.aspectMask = VulkanUtil::getAspectMask(srcSubresource.aspectMask, srcTexture->m_vkformat); region.imageSubresource.mipLevel = srcSubresource.mipLevel; region.imageSubresource.baseArrayLayer = srcSubresource.baseArrayLayer; region.imageSubresource.layerCount = srcSubresource.layerCount; @@ -963,9 +823,9 @@ void ResourceCommandEncoderImpl::copyTextureToBuffer( auto& api = m_commandBuffer->m_device->m_api; api.vkCmdCopyImageToBuffer( m_commandBuffer->m_commandBuffer, - image->m_image, - srcImageLayout, - buffer->m_buffer.m_buffer, + srcTexture->m_image, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dstBuffer->m_buffer.m_buffer, 1, ®ion ); @@ -978,7 +838,7 @@ Result RenderCommandEncoderImpl::beginPass(const RenderPassDesc& desc) auto& api = *m_api; m_renderTargetViews.resize(desc.colorAttachmentCount); - m_renderTargetFinalStates.resize(desc.colorAttachmentCount); + m_resolveTargetViews.resize(desc.colorAttachmentCount); short_vector colorAttachmentInfos; VkRenderingAttachmentInfoKHR depthAttachmentInfo = {VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR}; VkRenderingAttachmentInfoKHR stencilAttachmentInfo = {VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR}; @@ -998,13 +858,20 @@ Result RenderCommandEncoderImpl::beginPass(const RenderPassDesc& desc) TextureViewImpl* view = static_cast(attachment.view); if (!view) return SLANG_FAIL; + TextureViewImpl* resolveView = static_cast(attachment.resolveTarget); m_renderTargetViews[i] = view; - m_renderTargetFinalStates[i] = attachment.finalState; + m_resolveTargetViews[i] = resolveView; // Transition state - ITexture* texture = view->m_texture; - textureBarrier(1, &texture, attachment.initialState, ResourceState::RenderTarget); + m_commandBuffer + ->requireTextureState(view->m_texture, view->m_desc.subresourceRange, ResourceState::RenderTarget); + if (resolveView) + m_commandBuffer->requireTextureState( + resolveView->m_texture, + resolveView->m_desc.subresourceRange, + ResourceState::ResolveDestination + ); // Determine render area const TextureViewDesc& viewDesc = view->m_desc; @@ -1022,6 +889,12 @@ Result RenderCommandEncoderImpl::beginPass(const RenderPassDesc& desc) VkRenderingAttachmentInfoKHR attachmentInfo = {VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR}; attachmentInfo.imageView = static_cast(attachment.view)->getView().imageView; attachmentInfo.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + if (attachment.resolveTarget) + { + attachmentInfo.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT; + attachmentInfo.resolveImageView = resolveView->getView().imageView; + attachmentInfo.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } attachmentInfo.loadOp = translateLoadOp(attachment.loadOp); attachmentInfo.storeOp = translateStoreOp(attachment.storeOp); attachmentInfo.clearValue.color.float32[0] = attachment.clearValue[0]; @@ -1040,12 +913,13 @@ Result RenderCommandEncoderImpl::beginPass(const RenderPassDesc& desc) return SLANG_FAIL; m_depthStencilView = static_cast(desc.depthStencilAttachment->view); - m_depthStencilCurrentState = attachment.depthReadOnly ? ResourceState::DepthRead : ResourceState::DepthWrite; - m_depthStencilFinalState = desc.depthStencilAttachment->finalState; // Transition state - ITexture* texture = view->m_texture; - textureBarrier(1, &texture, attachment.initialState, m_depthStencilCurrentState); + m_commandBuffer->requireTextureState( + view->m_texture, + view->m_desc.subresourceRange, + attachment.depthReadOnly ? ResourceState::DepthRead : ResourceState::DepthWrite + ); // Determine render area const TextureViewDesc& viewDesc = view->m_desc; @@ -1096,18 +970,8 @@ void RenderCommandEncoderImpl::endEncoding() auto& api = *m_api; api.vkCmdEndRenderingKHR(m_vkCommandBuffer); - for (Index i = 0; i < m_renderTargetViews.size(); ++i) - { - ITexture* texture = m_renderTargetViews[i]->m_texture; - textureBarrier(1, &texture, ResourceState::RenderTarget, m_renderTargetFinalStates[i]); - } - if (m_depthStencilView) - { - ITexture* texture = m_depthStencilView->m_texture; - textureBarrier(1, &texture, m_depthStencilCurrentState, m_depthStencilFinalState); - } - m_renderTargetViews.clear(); + m_resolveTargetViews.clear(); m_depthStencilView = nullptr; endEncodingImpl(); diff --git a/src/vulkan/vk-command-encoder.h b/src/vulkan/vk-command-encoder.h index 5a8fc84..cf06166 100644 --- a/src/vulkan/vk-command-encoder.h +++ b/src/vulkan/vk-command-encoder.h @@ -31,16 +31,9 @@ class CommandEncoderImpl : public ICommandEncoder virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; } public: + virtual SLANG_NO_THROW void SLANG_MCALL setBufferState(IBuffer* buffer, ResourceState state) override; virtual SLANG_NO_THROW void SLANG_MCALL - textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) override; - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst - ) override; - virtual SLANG_NO_THROW void SLANG_MCALL - bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) override; + setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) override; virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) override; virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override; @@ -108,11 +101,9 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( ITexture* dst, - ResourceState dstState, SubresourceRange dstSubresource, Offset3D dstOffset, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -137,15 +128,6 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman bool clearStencil ) override; - virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( - ITexture* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITexture* dest, - ResourceState destState, - SubresourceRange destRange - ) override; - virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery(IQueryPool* queryPool, GfxIndex index, GfxCount count, IBuffer* buffer, Offset offset) override; @@ -155,7 +137,6 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman Size dstSize, Size dstRowStride, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -178,10 +159,8 @@ class RenderCommandEncoderImpl : public IRenderCommandEncoder, public CommandEnc public: short_vector> m_renderTargetViews; - short_vector m_renderTargetFinalStates; + short_vector> m_resolveTargetViews; RefPtr m_depthStencilView; - ResourceState m_depthStencilCurrentState; - ResourceState m_depthStencilFinalState; std::vector m_viewports; std::vector m_scissorRects; diff --git a/src/vulkan/vk-device.cpp b/src/vulkan/vk-device.cpp index d0d07d0..ecb46a8 100644 --- a/src/vulkan/vk-device.cpp +++ b/src/vulkan/vk-device.cpp @@ -1123,13 +1123,7 @@ Result DeviceImpl::createSwapchain(const ISwapchain::Desc& desc, WindowHandle wi return SLANG_OK; } -Result DeviceImpl::readTexture( - ITexture* texture, - ResourceState state, - ISlangBlob** outBlob, - Size* outRowPitch, - Size* outPixelSize -) +Result DeviceImpl::readTexture(ITexture* texture, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) { TextureImpl* textureImpl = static_cast(texture); @@ -1171,7 +1165,37 @@ Result DeviceImpl::readTexture( VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer(); VkImage srcImage = textureImpl->m_image; - VkImageLayout srcImageLayout = VulkanUtil::getImageLayoutFromState(state); + + VkImageMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.image = srcImage; + barrier.oldLayout = translateImageLayout(textureImpl->m_desc.defaultState); + barrier.newLayout = translateImageLayout(ResourceState::CopySource); + barrier.subresourceRange.aspectMask = getAspectMaskFromFormat(VulkanUtil::getVkFormat(textureImpl->m_desc.format)); + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.srcAccessMask = calcAccessFlags(textureImpl->m_desc.defaultState); + barrier.dstAccessMask = calcAccessFlags(ResourceState::CopySource); + + VkPipelineStageFlags srcStageFlags = calcPipelineStageFlags(textureImpl->m_desc.defaultState, true); + VkPipelineStageFlags dstStageFlags = calcPipelineStageFlags(ResourceState::CopySource, false); + + m_api.vkCmdPipelineBarrier( + commandBuffer, + srcStageFlags, + dstStageFlags, + VkDependencyFlags(0), + 0, + nullptr, + 0, + nullptr, + 1, + &barrier + ); + + VkImageLayout srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; Offset dstOffset = 0; for (int i = 0; i < arrayLayerCount; ++i) @@ -1202,6 +1226,23 @@ Result DeviceImpl::readTexture( } } + std::swap(barrier.oldLayout, barrier.newLayout); + std::swap(barrier.srcAccessMask, barrier.dstAccessMask); + std::swap(srcStageFlags, dstStageFlags); + + m_api.vkCmdPipelineBarrier( + commandBuffer, + srcStageFlags, + dstStageFlags, + VkDependencyFlags(0), + 0, + nullptr, + 0, + nullptr, + 1, + &barrier + ); + m_deviceQueue.flushAndWait(); auto blob = OwnedBlob::create(bufferSize); @@ -1237,11 +1278,51 @@ Result DeviceImpl::readBuffer(IBuffer* inBuffer, Offset offset, Size size, ISlan // Copy from real buffer to staging buffer VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer(); + VkBufferMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.srcAccessMask = calcAccessFlags(buffer->m_desc.defaultState); + barrier.dstAccessMask = calcAccessFlags(ResourceState::CopyDestination); + barrier.buffer = buffer->m_buffer.m_buffer; + barrier.offset = 0; + barrier.size = buffer->m_desc.size; + + VkPipelineStageFlags srcStageFlags = calcPipelineStageFlags(buffer->m_desc.defaultState, true); + VkPipelineStageFlags dstStageFlags = calcPipelineStageFlags(ResourceState::CopySource, false); + + m_api.vkCmdPipelineBarrier( + commandBuffer, + srcStageFlags, + dstStageFlags, + VkDependencyFlags(0), + 0, + nullptr, + 1, + &barrier, + 0, + nullptr + ); + VkBufferCopy copyInfo = {}; copyInfo.size = size; copyInfo.srcOffset = offset; m_api.vkCmdCopyBuffer(commandBuffer, buffer->m_buffer.m_buffer, staging.m_buffer, 1, ©Info); + std::swap(barrier.srcAccessMask, barrier.dstAccessMask); + std::swap(srcStageFlags, dstStageFlags); + + m_api.vkCmdPipelineBarrier( + commandBuffer, + srcStageFlags, + dstStageFlags, + VkDependencyFlags(0), + 0, + nullptr, + 1, + &barrier, + 0, + nullptr + ); + m_deviceQueue.flushAndWait(); auto blob = OwnedBlob::create(size); diff --git a/src/vulkan/vk-device.h b/src/vulkan/vk-device.h index 3f85e70..98f2132 100644 --- a/src/vulkan/vk-device.h +++ b/src/vulkan/vk-device.h @@ -60,8 +60,7 @@ class DeviceImpl : public Device virtual SLANG_NO_THROW Result SLANG_MCALL createQueryPool(const QueryPoolDesc& desc, IQueryPool** outPool) override; virtual SLANG_NO_THROW Result SLANG_MCALL - readTexture(ITexture* texture, ResourceState state, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) - override; + readTexture(ITexture* texture, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) override; virtual SLANG_NO_THROW Result SLANG_MCALL readBuffer(IBuffer* buffer, Offset offset, Size size, ISlangBlob** outBlob) override; diff --git a/src/vulkan/vk-helper-functions.cpp b/src/vulkan/vk-helper-functions.cpp index cfdfe1e..0bc622f 100644 --- a/src/vulkan/vk-helper-functions.cpp +++ b/src/vulkan/vk-helper-functions.cpp @@ -66,8 +66,6 @@ VkImageLayout translateImageLayout(ResourceState state) { case ResourceState::Undefined: return VK_IMAGE_LAYOUT_UNDEFINED; - case ResourceState::PreInitialized: - return VK_IMAGE_LAYOUT_PREINITIALIZED; case ResourceState::UnorderedAccess: return VK_IMAGE_LAYOUT_GENERAL; case ResourceState::RenderTarget: @@ -77,8 +75,6 @@ VkImageLayout translateImageLayout(ResourceState state) case ResourceState::DepthWrite: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; case ResourceState::ShaderResource: - case ResourceState::NonPixelShaderResource: - case ResourceState::PixelShaderResource: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; case ResourceState::ResolveDestination: case ResourceState::CopyDestination: @@ -100,7 +96,6 @@ VkAccessFlagBits calcAccessFlags(ResourceState state) { case ResourceState::Undefined: case ResourceState::Present: - case ResourceState::PreInitialized: return VkAccessFlagBits(0); case ResourceState::VertexBuffer: return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; @@ -111,8 +106,6 @@ VkAccessFlagBits calcAccessFlags(ResourceState state) case ResourceState::RenderTarget: return VkAccessFlagBits(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT); case ResourceState::ShaderResource: - case ResourceState::NonPixelShaderResource: - case ResourceState::PixelShaderResource: return VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; case ResourceState::UnorderedAccess: return VkAccessFlagBits(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); @@ -149,7 +142,6 @@ VkPipelineStageFlagBits calcPipelineStageFlags(ResourceState state, bool src) switch (state) { case ResourceState::Undefined: - case ResourceState::PreInitialized: SLANG_RHI_ASSERT(src); return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; case ResourceState::VertexBuffer: @@ -164,8 +156,6 @@ VkPipelineStageFlagBits calcPipelineStageFlags(ResourceState state, bool src) VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR ); case ResourceState::ShaderResource: - case ResourceState::NonPixelShaderResource: - case ResourceState::PixelShaderResource: return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; case ResourceState::RenderTarget: return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; @@ -251,8 +241,6 @@ VkImageUsageFlagBits _calcImageUsageFlags(ResourceState state) case ResourceState::DepthRead: return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; case ResourceState::ShaderResource: - case ResourceState::NonPixelShaderResource: - case ResourceState::PixelShaderResource: return VK_IMAGE_USAGE_SAMPLED_BIT; case ResourceState::UnorderedAccess: return VK_IMAGE_USAGE_STORAGE_BIT; diff --git a/src/vulkan/vk-shader-object.cpp b/src/vulkan/vk-shader-object.cpp index 84a9bbb..5a43334 100644 --- a/src/vulkan/vk-shader-object.cpp +++ b/src/vulkan/vk-shader-object.cpp @@ -3,6 +3,8 @@ #include "vk-command-encoder.h" #include "vk-transient-heap.h" +#include "../state-tracking.h" + namespace rhi::vk { Result ShaderObjectImpl::create(IDevice* device, ShaderObjectLayoutImpl* layout, ShaderObjectImpl** outShaderObject) @@ -81,17 +83,28 @@ Result ShaderObjectImpl::setBinding(ShaderOffset const& offset, Binding binding) Index bindingIndex = bindingRange.baseIndex + offset.bindingArrayIndex; + ResourceSlot& slot = m_resources[bindingIndex]; + switch (binding.type) { case BindingType::Buffer: { BufferImpl* buffer = static_cast(binding.resource.get()); - ResourceSlot slot; slot.type = BindingType::Buffer; slot.resource = buffer; slot.format = slot.format != Format::Unknown ? slot.format : buffer->m_desc.format; slot.bufferRange = buffer->resolveBufferRange(slot.bufferRange); - m_resources[bindingIndex] = slot; + switch (bindingRange.bindingType) + { + case slang::BindingType::TypedBuffer: + case slang::BindingType::RawBuffer: + slot.requiredState = ResourceState::ShaderResource; + break; + case slang::BindingType::MutableTypedBuffer: + case slang::BindingType::MutableRawBuffer: + slot.requiredState = ResourceState::UnorderedAccess; + break; + } break; } case BindingType::Texture: @@ -101,10 +114,17 @@ Result ShaderObjectImpl::setBinding(ShaderOffset const& offset, Binding binding) } case BindingType::TextureView: { - ResourceSlot slot; slot.type = BindingType::TextureView; slot.resource = static_cast(binding.resource.get()); - m_resources[bindingIndex] = slot; + switch (bindingRange.bindingType) + { + case slang::BindingType::Texture: + slot.requiredState = ResourceState::ShaderResource; + break; + case slang::BindingType::MutableTexture: + slot.requiredState = ResourceState::UnorderedAccess; + break; + } break; } case BindingType::Sampler: @@ -120,10 +140,8 @@ Result ShaderObjectImpl::setBinding(ShaderOffset const& offset, Binding binding) break; } case BindingType::AccelerationStructure: - ResourceSlot slot; slot.type = BindingType::AccelerationStructure; slot.resource = static_cast(binding.resource.get()); - m_resources[bindingIndex] = slot; break; } @@ -978,6 +996,49 @@ Result ShaderObjectImpl::bindAsConstantBuffer( return SLANG_OK; } +void ShaderObjectImpl::setResourceStates(StateTracking& stateTracking) +{ + for (const ResourceSlot& slot : m_resources) + { + switch (slot.type) + { + case BindingType::Buffer: + stateTracking.setBufferState(static_cast(slot.resource.get()), slot.requiredState); + break; + case BindingType::TextureView: + { + TextureViewImpl* textureView = static_cast(slot.resource.get()); + stateTracking + .setTextureState(textureView->m_texture, textureView->m_desc.subresourceRange, slot.requiredState); + break; + } + case BindingType::AccelerationStructure: + // TODO STATE_TRACKING need state transition? + break; + } + } + + for (const CombinedTextureSamplerSlot& slot : m_combinedTextureSamplers) + { + if (slot.textureView) + { + stateTracking.setTextureState( + slot.textureView->m_texture, + slot.textureView->m_desc.subresourceRange, + ResourceState::ShaderResource + ); + } + } + + for (auto& subObject : m_objects) + { + if (subObject) + { + subObject->setResourceStates(stateTracking); + } + } +} + Result ShaderObjectImpl::_getSpecializedLayout(ShaderObjectLayoutImpl** outLayout) { if (!m_specializedLayout) @@ -1130,6 +1191,15 @@ Result RootShaderObjectImpl::copyFrom(IShaderObject* object, ITransientResourceH return SLANG_FAIL; } +void RootShaderObjectImpl::setResourceStates(StateTracking& stateTracking) +{ + ShaderObjectImpl::setResourceStates(stateTracking); + for (auto& entryPoint : m_entryPoints) + { + entryPoint->setResourceStates(stateTracking); + } +} + Result RootShaderObjectImpl::bindAsRoot( CommandEncoderImpl* encoder, RootBindingContext& context, diff --git a/src/vulkan/vk-shader-object.h b/src/vulkan/vk-shader-object.h index 9f13bf5..56b80e0 100644 --- a/src/vulkan/vk-shader-object.h +++ b/src/vulkan/vk-shader-object.h @@ -6,6 +6,8 @@ #include "vk-sampler.h" #include "vk-shader-object-layout.h" +#include "../state-tracking.h" + #include namespace rhi::vk { @@ -19,6 +21,7 @@ struct ResourceSlot { BufferRange bufferRange = kEntireBuffer; }; + ResourceState requiredState = ResourceState::Undefined; operator bool() const { return type != BindingType::Unknown && resource; } }; @@ -182,6 +185,8 @@ class ShaderObjectImpl : public ShaderObjectBaseImpl m_resources; std::vector> m_samplers; std::vector m_combinedTextureSamplers; @@ -261,6 +266,8 @@ class RootShaderObjectImpl : public ShaderObjectImpl virtual SLANG_NO_THROW Result SLANG_MCALL copyFrom(IShaderObject* object, ITransientResourceHeap* transientHeap) override; + void setResourceStates(StateTracking& stateTracking); + /// Bind this object as a root shader object Result bindAsRoot(CommandEncoderImpl* encoder, RootBindingContext& context, RootShaderObjectLayout* layout); diff --git a/src/vulkan/vk-shader-table.cpp b/src/vulkan/vk-shader-table.cpp index e741b20..7ebcaf9 100644 --- a/src/vulkan/vk-shader-table.cpp +++ b/src/vulkan/vk-shader-table.cpp @@ -129,7 +129,7 @@ RefPtr ShaderTableImpl::createDeviceBuffer( /* regionCount: */ 1, ©Region ); - encoder->bufferBarrier(1, buffer.readRef(), ResourceState::CopyDestination, ResourceState::ShaderResource); + encoder->setBufferState(buffer, ResourceState::ShaderResource); RefPtr resultPtr = static_cast(buffer.get()); return _Move(resultPtr); } diff --git a/src/vulkan/vk-util.cpp b/src/vulkan/vk-util.cpp index 71378b3..761a494 100644 --- a/src/vulkan/vk-util.cpp +++ b/src/vulkan/vk-util.cpp @@ -295,8 +295,6 @@ VkImageLayout VulkanUtil::getImageLayoutFromState(ResourceState state) switch (state) { case ResourceState::ShaderResource: - case ResourceState::PixelShaderResource: - case ResourceState::NonPixelShaderResource: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; case ResourceState::UnorderedAccess: case ResourceState::General: @@ -653,8 +651,6 @@ VkImageLayout VulkanUtil::mapResourceStateToLayout(ResourceState state) case ResourceState::Undefined: return VK_IMAGE_LAYOUT_UNDEFINED; case ResourceState::ShaderResource: - case ResourceState::PixelShaderResource: - case ResourceState::NonPixelShaderResource: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; case ResourceState::UnorderedAccess: return VK_IMAGE_LAYOUT_GENERAL; diff --git a/src/wgpu/wgpu-command-encoder.cpp b/src/wgpu/wgpu-command-encoder.cpp index b7e9dfd..6ed3da0 100644 --- a/src/wgpu/wgpu-command-encoder.cpp +++ b/src/wgpu/wgpu-command-encoder.cpp @@ -133,22 +133,12 @@ Result CommandEncoderImpl::setPipelineWithRootObjectImpl(IPipeline* state, IShad return SLANG_OK; } -void CommandEncoderImpl::textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) +void CommandEncoderImpl::setBufferState(IBuffer* buffer, ResourceState state) { // WGPU doesn't have explicit barriers. } -void CommandEncoderImpl::textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst -) -{ - // WGPU doesn't have explicit barriers. -} - -void CommandEncoderImpl::bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) +void CommandEncoderImpl::setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) { // WGPU doesn't have explicit barriers. } @@ -197,11 +187,9 @@ void ResourceCommandEncoderImpl::copyBuffer(IBuffer* dst, Offset dstOffset, IBuf void ResourceCommandEncoderImpl::copyTexture( ITexture* dst, - ResourceState dstState, SubresourceRange dstSubresource, Offset3D dstOffset, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -217,7 +205,6 @@ void ResourceCommandEncoderImpl::copyTextureToBuffer( Size dstSize, Size dstRowStride, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -260,18 +247,6 @@ void ResourceCommandEncoderImpl::clearTexture( { } -void ResourceCommandEncoderImpl::resolveResource( - ITexture* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITexture* dest, - ResourceState destState, - SubresourceRange destRange -) -{ - SLANG_RHI_UNIMPLEMENTED("resolveResource"); -} - void ResourceCommandEncoderImpl::resolveQuery( IQueryPool* queryPool, GfxIndex index, @@ -303,6 +278,9 @@ Result RenderCommandEncoderImpl::init(CommandBufferImpl* commandBuffer, const Re const RenderPassColorAttachment& attachmentIn = desc.colorAttachments[i]; WGPURenderPassColorAttachment& attachment = colorAttachments[i]; attachment.view = static_cast(attachmentIn.view)->m_textureView; + attachment.resolveTarget = attachmentIn.resolveTarget + ? static_cast(attachmentIn.resolveTarget)->m_textureView + : nullptr; attachment.depthSlice = -1; // TODO not provided attachment.resolveTarget = nullptr; // TODO not provided attachment.loadOp = translateLoadOp(attachmentIn.loadOp); diff --git a/src/wgpu/wgpu-command-encoder.h b/src/wgpu/wgpu-command-encoder.h index e2bb985..1108999 100644 --- a/src/wgpu/wgpu-command-encoder.h +++ b/src/wgpu/wgpu-command-encoder.h @@ -34,16 +34,9 @@ class CommandEncoderImpl : public ICommandEncoder Result setPipelineWithRootObjectImpl(IPipeline* state, IShaderObject* rootObject); // ICommandEncoder implementation + virtual SLANG_NO_THROW void SLANG_MCALL setBufferState(IBuffer* buffer, ResourceState state) override; virtual SLANG_NO_THROW void SLANG_MCALL - textureBarrier(GfxCount count, ITexture* const* textures, ResourceState src, ResourceState dst) override; - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( - ITexture* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst - ) override; - virtual SLANG_NO_THROW void SLANG_MCALL - bufferBarrier(GfxCount count, IBuffer* const* buffers, ResourceState src, ResourceState dst) override; + setTextureState(ITexture* texture, SubresourceRange subresourceRange, ResourceState state) override; virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) override; virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override; @@ -69,11 +62,9 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( ITexture* dst, - ResourceState dstState, SubresourceRange dstSubresource, Offset3D dstOffset, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -85,7 +76,6 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman Size dstSize, Size dstRowStride, ITexture* src, - ResourceState srcState, SubresourceRange srcSubresource, Offset3D srcOffset, Extents extent @@ -113,15 +103,6 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder, public Comman bool clearStencil ) override; - virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( - ITexture* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITexture* dest, - ResourceState destState, - SubresourceRange destRange - ) override; - virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery(IQueryPool* queryPool, GfxIndex index, GfxCount count, IBuffer* buffer, Offset offset) override; }; diff --git a/src/wgpu/wgpu-device.cpp b/src/wgpu/wgpu-device.cpp index 6130523..f368afc 100644 --- a/src/wgpu/wgpu-device.cpp +++ b/src/wgpu/wgpu-device.cpp @@ -151,13 +151,7 @@ Result DeviceImpl::createSwapchain(const ISwapchain::Desc& desc, WindowHandle wi return SLANG_E_NOT_IMPLEMENTED; } -Result DeviceImpl::readTexture( - ITexture* texture, - ResourceState state, - ISlangBlob** outBlob, - Size* outRowPitch, - Size* outPixelSize -) +Result DeviceImpl::readTexture(ITexture* texture, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) { TextureImpl* textureImpl = static_cast(texture); diff --git a/src/wgpu/wgpu-device.h b/src/wgpu/wgpu-device.h index f4c6740..3b587bf 100644 --- a/src/wgpu/wgpu-device.h +++ b/src/wgpu/wgpu-device.h @@ -80,8 +80,7 @@ class DeviceImpl : public Device virtual SLANG_NO_THROW Result SLANG_MCALL createQueryPool(const QueryPoolDesc& desc, IQueryPool** outPool) override; virtual SLANG_NO_THROW Result SLANG_MCALL - readTexture(ITexture* texture, ResourceState state, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) - override; + readTexture(ITexture* texture, ISlangBlob** outBlob, Size* outRowPitch, Size* outPixelSize) override; virtual SLANG_NO_THROW Result SLANG_MCALL readBuffer(IBuffer* buffer, Offset offset, Size size, ISlangBlob** outBlob) override; diff --git a/tests/test-buffer-barrier.cpp b/tests/test-buffer-barrier.cpp index bf4d4ae..47bd029 100644 --- a/tests/test-buffer-barrier.cpp +++ b/tests/test-buffer-barrier.cpp @@ -55,9 +55,6 @@ void testBufferBarrier(GpuTestContext* ctx, DeviceType deviceType) ComPtr intermediateBuffer = createFloatBuffer(device, true, 4); ComPtr outputBuffer = createFloatBuffer(device, true, 4); - auto insertBarrier = [](ICommandEncoder* encoder, IBuffer* buffer, ResourceState before, ResourceState after) - { encoder->bufferBarrier(1, &buffer, before, after); }; - // We have done all the set up work, now it is time to start recording a command buffer for // GPU execution. { @@ -75,8 +72,7 @@ void testBufferBarrier(GpuTestContext* ctx, DeviceType deviceType) encoder->dispatchCompute(1, 1, 1); - // Insert barrier to ensure writes to intermediateBuffer are complete before the next shader starts executing - insertBarrier(encoder, intermediateBuffer, ResourceState::UnorderedAccess, ResourceState::ShaderResource); + // Resource transition is automatically handled. // Write intermediateBuffer to outputBuffer auto rootObjectB = encoder->bindPipeline(programB.pipeline); diff --git a/tests/test-clear-texture.cpp b/tests/test-clear-texture.cpp index c6e259d..3431b66 100644 --- a/tests/test-clear-texture.cpp +++ b/tests/test-clear-texture.cpp @@ -38,7 +38,6 @@ void testClearTexture(GpuTestContext* ctx, DeviceType deviceType) clearValue.color.floatValues[2] = 0.2f; clearValue.color.floatValues[3] = 0.1f; resourceEncoder->clearResourceView(rtv, &clearValue, ClearResourceViewFlags::FloatClearValues); - resourceEncoder->textureBarrier(srcTexture, ResourceState::RenderTarget, ResourceState::CopySource); resourceEncoder->endEncoding(); commandBuffer->close(); @@ -48,7 +47,7 @@ void testClearTexture(GpuTestContext* ctx, DeviceType deviceType) ComPtr blob; size_t rowPitch, pixelSize; - device->readTexture(srcTexture, ResourceState::CopySource, blob.writeRef(), &rowPitch, &pixelSize); + device->readTexture(srcTexture, blob.writeRef(), &rowPitch, &pixelSize); float* data = (float*)blob->getBufferPointer(); for (int i = 0; i < 4; i++) { diff --git a/tests/test-compute-smoke.cpp b/tests/test-compute-smoke.cpp index 1907421..86be5a2 100644 --- a/tests/test-compute-smoke.cpp +++ b/tests/test-compute-smoke.cpp @@ -85,7 +85,7 @@ TEST_CASE("compute-smoke") DeviceType::Metal, DeviceType::CUDA, DeviceType::CPU, - DeviceType::WGPU, + // DeviceType::WGPU, } ); } diff --git a/tests/test-copy-texture.cpp b/tests/test-copy-texture.cpp index 4e16c0f..399adf0 100644 --- a/tests/test-copy-texture.cpp +++ b/tests/test-copy-texture.cpp @@ -130,37 +130,22 @@ struct BaseCopyTextureTest auto commandBuffer = transientHeap->createCommandBuffer(); auto encoder = commandBuffer->encodeResourceCommands(); - encoder->textureSubresourceBarrier( - srcTexture, - texCopyInfo.srcSubresource, - ResourceState::ShaderResource, - ResourceState::CopySource - ); encoder->copyTexture( dstTexture, - ResourceState::CopyDestination, texCopyInfo.dstSubresource, texCopyInfo.dstOffset, srcTexture, - ResourceState::CopySource, texCopyInfo.srcSubresource, texCopyInfo.srcOffset, texCopyInfo.extent ); - encoder->textureSubresourceBarrier( - dstTexture, - bufferCopyInfo.srcSubresource, - ResourceState::CopyDestination, - ResourceState::CopySource - ); encoder->copyTextureToBuffer( resultsBuffer, bufferCopyInfo.bufferOffset, bufferCopyInfo.bufferSize, alignedRowStride, dstTexture, - ResourceState::CopySource, bufferCopyInfo.srcSubresource, bufferCopyInfo.textureOffset, bufferCopyInfo.extent diff --git a/tests/test-instanced-draw.cpp b/tests/test-instanced-draw.cpp index 4f1a164..b04fb9d 100644 --- a/tests/test-instanced-draw.cpp +++ b/tests/test-instanced-draw.cpp @@ -183,9 +183,7 @@ class BaseDrawTest ComPtr resultBlob; size_t rowPitch = 0; size_t pixelSize = 0; - REQUIRE_CALL( - device->readTexture(colorBuffer, ResourceState::CopySource, resultBlob.writeRef(), &rowPitch, &pixelSize) - ); + REQUIRE_CALL(device->readTexture(colorBuffer, resultBlob.writeRef(), &rowPitch, &pixelSize)); auto result = (float*)resultBlob->getBufferPointer(); int cursor = 0; @@ -221,8 +219,6 @@ struct DrawInstancedTest : BaseDrawTest colorAttachment.view = colorBufferView; colorAttachment.loadOp = LoadOp::Clear; colorAttachment.storeOp = StoreOp::Store; - colorAttachment.initialState = ResourceState::RenderTarget; - colorAttachment.finalState = ResourceState::CopySource; RenderPassDesc renderPass; renderPass.colorAttachments = &colorAttachment; renderPass.colorAttachmentCount = 1; @@ -279,8 +275,6 @@ struct DrawIndexedInstancedTest : BaseDrawTest colorAttachment.view = colorBufferView; colorAttachment.loadOp = LoadOp::Clear; colorAttachment.storeOp = StoreOp::Store; - colorAttachment.initialState = ResourceState::RenderTarget; - colorAttachment.finalState = ResourceState::CopySource; RenderPassDesc renderPass; renderPass.colorAttachments = &colorAttachment; renderPass.colorAttachmentCount = 1; @@ -363,8 +357,6 @@ struct DrawIndirectTest : BaseDrawTest colorAttachment.view = colorBufferView; colorAttachment.loadOp = LoadOp::Clear; colorAttachment.storeOp = StoreOp::Store; - colorAttachment.initialState = ResourceState::RenderTarget; - colorAttachment.finalState = ResourceState::CopySource; RenderPassDesc renderPass; renderPass.colorAttachments = &colorAttachment; renderPass.colorAttachmentCount = 1; @@ -446,8 +438,6 @@ struct DrawIndexedIndirectTest : BaseDrawTest colorAttachment.view = colorBufferView; colorAttachment.loadOp = LoadOp::Clear; colorAttachment.storeOp = StoreOp::Store; - colorAttachment.initialState = ResourceState::RenderTarget; - colorAttachment.finalState = ResourceState::CopySource; RenderPassDesc renderPass; renderPass.colorAttachments = &colorAttachment; renderPass.colorAttachmentCount = 1; diff --git a/tests/test-mutable-shader-object.cpp b/tests/test-mutable-shader-object.cpp index d3fecc7..8c5822a 100644 --- a/tests/test-mutable-shader-object.cpp +++ b/tests/test-mutable-shader-object.cpp @@ -67,14 +67,6 @@ void testMutableShaderObject(GpuTestContext* ctx, DeviceType deviceType) entryPointCursor.getPath("transformer").setObject(transformerVersion); encoder->dispatchCompute(1, 1, 1); - encoder->endEncoding(); - - auto barrierEncoder = commandBuffer->encodeResourceCommands(); - barrierEncoder - ->bufferBarrier(1, buffer.readRef(), ResourceState::UnorderedAccess, ResourceState::UnorderedAccess); - barrierEncoder->endEncoding(); - - encoder = commandBuffer->encodeComputeCommands(); rootObject = encoder->bindPipeline(pipeline); entryPointCursor = ShaderCursor(rootObject->getEntryPoint(0)); diff --git a/tests/test-ray-tracing.cpp b/tests/test-ray-tracing.cpp index a53fcd1..7b6c08e 100644 --- a/tests/test-ray-tracing.cpp +++ b/tests/test-ray-tracing.cpp @@ -346,17 +346,7 @@ struct BaseRayTracingTest ComPtr resultBlob; size_t rowPitch = 0; size_t pixelSize = 0; - auto cmdBuffer = transientHeap->createCommandBuffer(); - auto encoder = cmdBuffer->encodeResourceCommands(); - encoder->textureBarrier(resultTexture.get(), ResourceState::UnorderedAccess, ResourceState::CopySource); - encoder->endEncoding(); - cmdBuffer->close(); - queue->executeCommandBuffer(cmdBuffer.get()); - queue->waitOnHost(); - - REQUIRE_CALL( - device->readTexture(resultTexture, ResourceState::CopySource, resultBlob.writeRef(), &rowPitch, &pixelSize) - ); + REQUIRE_CALL(device->readTexture(resultTexture, resultBlob.writeRef(), &rowPitch, &pixelSize)); #if 0 // for debugging only writeImage("test.hdr", resultBlob, width, height, (uint32_t)rowPitch, (uint32_t)pixelSize); #endif diff --git a/tests/test-resolve-resource-tests.cpp b/tests/test-resolve-resource-tests.cpp index b1d9528..ca4af97 100644 --- a/tests/test-resolve-resource-tests.cpp +++ b/tests/test-resolve-resource-tests.cpp @@ -58,6 +58,7 @@ struct BaseResolveResourceTest ComPtr msaaTexture; ComPtr msaaTextureView; ComPtr dstTexture; + ComPtr dstTextureView; ComPtr transientHeap; ComPtr pipeline; @@ -103,7 +104,7 @@ struct BaseResolveResourceTest dstTexDesc.numMipLevels = dstTextureInfo.numMipLevels; dstTexDesc.arrayLength = dstTextureInfo.arrayLength; dstTexDesc.size = dstTextureInfo.extent; - dstTexDesc.usage = TextureUsage::ResolveDestination | TextureUsage::CopySource; + dstTexDesc.usage = TextureUsage::ResolveDestination | TextureUsage::CopySource | TextureUsage::RenderTarget; dstTexDesc.defaultState = ResourceState::ResolveDestination; dstTexDesc.format = format; @@ -150,6 +151,7 @@ struct BaseResolveResourceTest TextureViewDesc textureViewDesc = {}; textureViewDesc.format = format; REQUIRE_CALL(device->createTextureView(msaaTexture, textureViewDesc, msaaTextureView.writeRef())); + REQUIRE_CALL(device->createTextureView(dstTexture, textureViewDesc, dstTextureView.writeRef())); } void submitGPUWork(SubresourceRange msaaSubresource, SubresourceRange dstSubresource, Extents extent) @@ -166,10 +168,9 @@ struct BaseResolveResourceTest RenderPassColorAttachment colorAttachment; colorAttachment.view = msaaTextureView; + colorAttachment.resolveTarget = dstTextureView; colorAttachment.loadOp = LoadOp::Clear; colorAttachment.storeOp = StoreOp::Store; - colorAttachment.initialState = ResourceState::RenderTarget; - colorAttachment.finalState = ResourceState::ResolveSource; RenderPassDesc renderPass; renderPass.colorAttachments = &colorAttachment; renderPass.colorAttachmentCount = 1; @@ -187,23 +188,6 @@ struct BaseResolveResourceTest renderEncoder->draw(kVertexCount, 0); renderEncoder->endEncoding(); - auto resourceEncoder = commandBuffer->encodeResourceCommands(); - - resourceEncoder->resolveResource( - msaaTexture, - ResourceState::ResolveSource, - msaaSubresource, - dstTexture, - ResourceState::ResolveDestination, - dstSubresource - ); - resourceEncoder->textureSubresourceBarrier( - dstTexture, - dstSubresource, - ResourceState::ResolveDestination, - ResourceState::CopySource - ); - resourceEncoder->endEncoding(); commandBuffer->close(); queue->executeCommandBuffer(commandBuffer); queue->waitOnHost(); @@ -223,9 +207,7 @@ struct BaseResolveResourceTest ComPtr resultBlob; size_t rowPitch = 0; size_t pixelSize = 0; - REQUIRE_CALL( - device->readTexture(dstTexture, ResourceState::CopySource, resultBlob.writeRef(), &rowPitch, &pixelSize) - ); + REQUIRE_CALL(device->readTexture(dstTexture, resultBlob.writeRef(), &rowPitch, &pixelSize)); auto result = (float*)resultBlob->getBufferPointer(); int cursor = 0; diff --git a/tests/test-resource-states.cpp b/tests/test-resource-states.cpp index e8823a3..ecdc6b3 100644 --- a/tests/test-resource-states.cpp +++ b/tests/test-resource-states.cpp @@ -34,8 +34,6 @@ void testBufferResourceStates(GpuTestContext* ctx, DeviceType deviceType) ResourceState::CopyDestination, // ResourceState::AccelerationStructure, // ResourceState::AccelerationStructureBuildInput, - ResourceState::PixelShaderResource, - ResourceState::NonPixelShaderResource, }; BufferDesc bufferDesc = {}; @@ -47,20 +45,16 @@ void testBufferResourceStates(GpuTestContext* ctx, DeviceType deviceType) ComPtr buffer; REQUIRE_CALL(device->createBuffer(bufferDesc, nullptr, buffer.writeRef())); - auto commandBuffer = transientHeap->createCommandBuffer(); - auto encoder = commandBuffer->encodeResourceCommands(); - - ResourceState currentState = buffer->getDesc().defaultState; - for (ResourceState state : allowedStates) { - encoder->bufferBarrier(buffer, currentState, state); - currentState = state; + auto commandBuffer = transientHeap->createCommandBuffer(); + auto encoder = commandBuffer->encodeResourceCommands(); + encoder->setBufferState(buffer, state); + encoder->endEncoding(); + commandBuffer->close(); + queue->executeCommandBuffer(commandBuffer); } - encoder->endEncoding(); - commandBuffer->close(); - queue->executeCommandBuffer(commandBuffer); queue->waitOnHost(); } @@ -129,20 +123,16 @@ void testTextureResourceStates(GpuTestContext* ctx, DeviceType deviceType) ComPtr texture; REQUIRE_CALL(device->createTexture(texDesc, nullptr, texture.writeRef())); - auto commandBuffer = transientHeap->createCommandBuffer(); - auto encoder = commandBuffer->encodeResourceCommands(); - - ResourceState currentState = texture->getDesc().defaultState; - for (ResourceState state : allowedStates) { - encoder->textureBarrier(texture, currentState, state); - currentState = state; + auto commandBuffer = transientHeap->createCommandBuffer(); + auto encoder = commandBuffer->encodeResourceCommands(); + encoder->setTextureState(texture, state); + encoder->endEncoding(); + commandBuffer->close(); + queue->executeCommandBuffer(commandBuffer); } - encoder->endEncoding(); - commandBuffer->close(); - queue->executeCommandBuffer(commandBuffer); queue->waitOnHost(); } } diff --git a/tests/test-root-mutable-shader-object.cpp b/tests/test-root-mutable-shader-object.cpp index 64f88ca..22906d8 100644 --- a/tests/test-root-mutable-shader-object.cpp +++ b/tests/test-root-mutable-shader-object.cpp @@ -64,11 +64,6 @@ void testRootMutableShaderObject(GpuTestContext* ctx, DeviceType deviceType) encoder->endEncoding(); } - auto barrierEncoder = commandBuffer->encodeResourceCommands(); - barrierEncoder - ->bufferBarrier(1, buffer.readRef(), ResourceState::UnorderedAccess, ResourceState::UnorderedAccess); - barrierEncoder->endEncoding(); - // Mutate `transformer` object and run again. c = 2.0f; ShaderCursor(transformer).getPath("c").setData(&c, sizeof(float)); diff --git a/tests/test-shader-cache.cpp b/tests/test-shader-cache.cpp index 9aab10e..338fe23 100644 --- a/tests/test-shader-cache.cpp +++ b/tests/test-shader-cache.cpp @@ -797,8 +797,6 @@ struct ShaderCacheTestGraphics : ShaderCacheTest colorAttachment.view = colorBufferView; colorAttachment.loadOp = LoadOp::Clear; colorAttachment.storeOp = StoreOp::Store; - colorAttachment.initialState = ResourceState::RenderTarget; - colorAttachment.finalState = ResourceState::CopySource; RenderPassDesc renderPass; renderPass.colorAttachments = &colorAttachment; renderPass.colorAttachmentCount = 1; diff --git a/tests/test-shared-texture.cpp b/tests/test-shared-texture.cpp index 0a95717..e76e74f 100644 --- a/tests/test-shared-texture.cpp +++ b/tests/test-shared-texture.cpp @@ -142,7 +142,7 @@ void testSharedTexture(GpuTestContext* ctx, DeviceType deviceType) // Reading back the buffer from srcDevice to make sure it's been filled in before reading anything back from // dstDevice // TODO: Implement actual synchronization (and not this hacky solution) - compareComputeResult(dstDevice, dstTexture, ResourceState::ShaderResource, texData, 32, 2); + compareComputeResult(dstDevice, dstTexture, texData, 32, 2); setUpAndRunShader(dstDevice, dstTexture, floatResults, "copyTexFloat4"); compareComputeResult( diff --git a/tests/test-texture-types.cpp b/tests/test-texture-types.cpp index 9434b18..1faa4b6 100644 --- a/tests/test-texture-types.cpp +++ b/tests/test-texture-types.cpp @@ -21,6 +21,7 @@ struct TextureTest RefPtr validationFormat; ComPtr texture; + ComPtr textureView; ComPtr sampler; ComPtr resultsBuffer; @@ -156,9 +157,6 @@ struct TextureAccessTest : TextureTest auto bufferElementCount = width * height * depth; encoder->dispatchCompute(bufferElementCount, 1, 1); - - encoder->textureBarrier(texture, texture->getDesc().defaultState, ResourceState::CopySource); - encoder->endEncoding(); commandBuffer->close(); queue->executeCommandBuffer(commandBuffer); @@ -193,9 +191,7 @@ struct TextureAccessTest : TextureTest ComPtr textureBlob; size_t rowPitch; size_t pixelSize; - REQUIRE_CALL( - device->readTexture(texture, ResourceState::CopySource, textureBlob.writeRef(), &rowPitch, &pixelSize) - ); + REQUIRE_CALL(device->readTexture(texture, textureBlob.writeRef(), &rowPitch, &pixelSize)); auto textureValues = (uint8_t*)textureBlob->getBufferPointer(); ValidationTextureData textureResults; @@ -341,6 +337,8 @@ struct RenderTargetTests : TextureTest REQUIRE_CALL(device->createTexture(textureDesc, textureInfo->subresourceDatas.data(), texture.writeRef())); + REQUIRE_CALL(device->createTextureView(texture, {}, textureView.writeRef())); + InputLayoutDesc inputLayoutDesc = {}; inputLayoutDesc.inputElementCount = SLANG_COUNT_OF(inputElements); inputLayoutDesc.inputElements = inputElements; @@ -391,10 +389,12 @@ struct RenderTargetTests : TextureTest RenderPassColorAttachment colorAttachment; colorAttachment.view = renderTextureView; + if (sampleCount > 1) + { + colorAttachment.resolveTarget = textureView; + } colorAttachment.loadOp = LoadOp::Clear; colorAttachment.storeOp = StoreOp::Store; - colorAttachment.initialState = ResourceState::RenderTarget; - colorAttachment.finalState = ResourceState::ResolveSource; RenderPassDesc renderPass; renderPass.colorAttachments = &colorAttachment; renderPass.colorAttachmentCount = 1; @@ -412,39 +412,6 @@ struct RenderTargetTests : TextureTest renderEncoder->draw(kVertexCount, 0); renderEncoder->endEncoding(); - auto resourceEncoder = commandBuffer->encodeResourceCommands(); - - if (sampleCount > 1) - { - SubresourceRange msaaSubresource = {}; - msaaSubresource.aspectMask = TextureAspect::Color; - msaaSubresource.mipLevel = 0; - msaaSubresource.mipLevelCount = 1; - msaaSubresource.baseArrayLayer = 0; - msaaSubresource.layerCount = 1; - - SubresourceRange dstSubresource = {}; - dstSubresource.aspectMask = TextureAspect::Color; - dstSubresource.mipLevel = 0; - dstSubresource.mipLevelCount = 1; - dstSubresource.baseArrayLayer = 0; - dstSubresource.layerCount = 1; - - resourceEncoder->resolveResource( - renderTexture, - ResourceState::ResolveSource, - msaaSubresource, - texture, - ResourceState::ResolveDestination, - dstSubresource - ); - resourceEncoder->textureBarrier(texture, ResourceState::ResolveDestination, ResourceState::CopySource); - } - else - { - resourceEncoder->textureBarrier(renderTexture, ResourceState::ResolveSource, ResourceState::CopySource); - } - resourceEncoder->endEncoding(); commandBuffer->close(); queue->executeCommandBuffer(commandBuffer); queue->waitOnHost(); @@ -485,19 +452,11 @@ struct RenderTargetTests : TextureTest size_t pixelSize; if (sampleCount > 1) { - REQUIRE_CALL( - device->readTexture(texture, ResourceState::CopySource, textureBlob.writeRef(), &rowPitch, &pixelSize) - ); + REQUIRE_CALL(device->readTexture(texture, textureBlob.writeRef(), &rowPitch, &pixelSize)); } else { - REQUIRE_CALL(device->readTexture( - renderTexture, - ResourceState::CopySource, - textureBlob.writeRef(), - &rowPitch, - &pixelSize - )); + REQUIRE_CALL(device->readTexture(renderTexture, textureBlob.writeRef(), &rowPitch, &pixelSize)); } auto textureValues = (float*)textureBlob->getBufferPointer(); diff --git a/tests/test-uint16-structured-buffer.cpp b/tests/test-uint16-structured-buffer.cpp index 805beae..a4dea8f 100644 --- a/tests/test-uint16-structured-buffer.cpp +++ b/tests/test-uint16-structured-buffer.cpp @@ -72,7 +72,7 @@ TEST_CASE("uint16-structured-buffer") // DeviceType::Metal, DeviceType::CPU, DeviceType::CUDA, - DeviceType::WGPU, // crashes + // DeviceType::WGPU, // crashes } ); } diff --git a/tests/testing.cpp b/tests/testing.cpp index e3b6357..0dad9ad 100644 --- a/tests/testing.cpp +++ b/tests/testing.cpp @@ -281,7 +281,6 @@ Result loadGraphicsProgram( void compareComputeResult( IDevice* device, ITexture* texture, - ResourceState state, void* expectedResult, size_t expectedResultRowPitch, size_t rowCount @@ -291,7 +290,7 @@ void compareComputeResult( ComPtr resultBlob; size_t rowPitch = 0; size_t pixelSize = 0; - REQUIRE_CALL(device->readTexture(texture, state, resultBlob.writeRef(), &rowPitch, &pixelSize)); + REQUIRE_CALL(device->readTexture(texture, resultBlob.writeRef(), &rowPitch, &pixelSize)); // Compare results. for (size_t row = 0; row < rowCount; row++) { diff --git a/tests/testing.h b/tests/testing.h index c3afccb..6487f39 100644 --- a/tests/testing.h +++ b/tests/testing.h @@ -81,7 +81,6 @@ void compareComputeResult( void compareComputeResult( IDevice* device, ITexture* texture, - ResourceState state, void* expectedResult, size_t expectedResultRowPitch, size_t rowCount