diff --git a/DirectX11/PlatformStructuredBuffer.cpp b/DirectX11/PlatformStructuredBuffer.cpp index ebfe1e41..e3b8e5f6 100644 --- a/DirectX11/PlatformStructuredBuffer.cpp +++ b/DirectX11/PlatformStructuredBuffer.cpp @@ -11,10 +11,12 @@ using namespace dx11; static const int NUM_STAGING_BUFFERS = 6; PlatformStructuredBuffer::PlatformStructuredBuffer() :buffer(0) + ,stagingWriteBuffer(0) ,shaderResourceView(0) ,unorderedAccessView(0) ,num_elements(0) ,element_bytesize(0) + ,computable(false) ,lastContext(NULL) ,read_data(0) #if _XBOX_ONE @@ -45,6 +47,7 @@ void PlatformStructuredBuffer::RestoreDeviceObjects(crossplatform::RenderPlatfor cpu_read = cpu_r; num_elements = ct; element_bytesize = unit_size; + this->computable = computable; D3D11_BUFFER_DESC sbDesc; memset(&sbDesc, 0, sizeof(sbDesc)); if (computable) @@ -114,6 +117,7 @@ void PlatformStructuredBuffer::RestoreDeviceObjects(crossplatform::RenderPlatfor if (renderPlatform && renderPlatform->GetMemoryInterface()) renderPlatform->GetMemoryInterface()->TrackVideoMemory(buffer, sbDesc.ByteWidth, "dx11::PlatformStructuredBuffer main buffer"); } + if (cpu_read) for (int i = 0; i < NUM_STAGING_BUFFERS; i++) { @@ -136,6 +140,21 @@ void PlatformStructuredBuffer::RestoreDeviceObjects(crossplatform::RenderPlatfor } } + // Needed for SetData on computable structured buffers: + if (computable) + { + sbDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + sbDesc.Usage = D3D11_USAGE_DYNAMIC; + sbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + sbDesc.MiscFlags = 0; + if (renderPlatform && renderPlatform->GetMemoryInterface()) + renderPlatform->GetMemoryInterface()->UntrackVideoMemory(stagingWriteBuffer); + V_CHECK(renderPlatform->AsD3D11Device()->CreateBuffer(&sbDesc, init_data != NULL ? &sbInit : NULL, &stagingWriteBuffer)); + if (renderPlatform && renderPlatform->GetMemoryInterface()) + renderPlatform->GetMemoryInterface()->TrackVideoMemory(stagingWriteBuffer, sbDesc.ByteWidth, "dx11::PlatformStructuredBuffer stagingWrite"); + + } + D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; memset(&srv_desc, 0, sizeof(srv_desc)); srv_desc.Format = DXGI_FORMAT_UNKNOWN; @@ -260,19 +279,40 @@ void PlatformStructuredBuffer::SetData(crossplatform::DeviceContext& deviceConte if (lastContext) { lastContext = deviceContext.asD3D11DeviceContext(); - D3D11_MAP map_type = D3D11_MAP_WRITE_DISCARD; - if (((dx11::RenderPlatform*)deviceContext.renderPlatform)->UsesFastSemantics()) - map_type = D3D11_MAP_WRITE; - HRESULT hr = lastContext->Map(buffer, 0, map_type, SIMUL_D3D11_MAP_FLAGS, &mapped); - if (hr == S_OK) + + if (computable) { - memcpy(mapped.pData, data, num_elements * element_bytesize); - mapped.RowPitch = 0; - mapped.DepthPitch = 0; - lastContext->Unmap(buffer, 0); + D3D11_MAP map_type = D3D11_MAP_WRITE_DISCARD; + if (((dx11::RenderPlatform *)deviceContext.renderPlatform)->UsesFastSemantics()) + map_type = D3D11_MAP_WRITE; + HRESULT hr = lastContext->Map(stagingWriteBuffer, 0, map_type, SIMUL_D3D11_MAP_FLAGS, &mapped); + if (hr == S_OK) + { + memcpy(mapped.pData, data, num_elements * element_bytesize); + mapped.RowPitch = 0; + mapped.DepthPitch = 0; + lastContext->Unmap(stagingWriteBuffer, 0); + lastContext->CopyResource(buffer, stagingWriteBuffer); + } + else + SIMUL_BREAK_ONCE("Map failed"); } else - SIMUL_BREAK_ONCE("Map failed"); + { + D3D11_MAP map_type = D3D11_MAP_WRITE_DISCARD; + if (((dx11::RenderPlatform *)deviceContext.renderPlatform)->UsesFastSemantics()) + map_type = D3D11_MAP_WRITE; + HRESULT hr = lastContext->Map(buffer, 0, map_type, SIMUL_D3D11_MAP_FLAGS, &mapped); + if (hr == S_OK) + { + memcpy(mapped.pData, data, num_elements * element_bytesize); + mapped.RowPitch = 0; + mapped.DepthPitch = 0; + lastContext->Unmap(buffer, 0); + } + else + SIMUL_BREAK_ONCE("Map failed"); + } } else SIMUL_BREAK_ONCE("Uninitialized device context"); @@ -307,14 +347,21 @@ void PlatformStructuredBuffer::InvalidateDeviceObjects() if (lastContext && mapped.pData && buffer) lastContext->Unmap(buffer, 0); mapped.pData = NULL; + SAFE_RELEASE(unorderedAccessView); SAFE_RELEASE(shaderResourceView); + + if (renderPlatform && renderPlatform->GetMemoryInterface()) + renderPlatform->GetMemoryInterface()->UntrackVideoMemory(stagingWriteBuffer); + SAFE_RELEASE(stagingWriteBuffer); + for (int i = 0; i < NUM_STAGING_BUFFERS; i++) { if (renderPlatform && renderPlatform->GetMemoryInterface()) renderPlatform->GetMemoryInterface()->UntrackVideoMemory(stagingBuffers[i]); SAFE_RELEASE(stagingBuffers[i]); } + num_elements = 0; #if SIMUL_D3D11_MAP_USAGE_DEFAULT_PLACEMENT if (renderPlatform && renderPlatform->GetMemoryInterface()) diff --git a/DirectX11/PlatformStructuredBuffer.h b/DirectX11/PlatformStructuredBuffer.h index 46416c6b..4009f636 100644 --- a/DirectX11/PlatformStructuredBuffer.h +++ b/DirectX11/PlatformStructuredBuffer.h @@ -14,11 +14,13 @@ namespace platform { ID3D11Buffer* buffer; ID3D11Buffer** stagingBuffers; + ID3D11Buffer* stagingWriteBuffer; ID3D11ShaderResourceView* shaderResourceView; ID3D11UnorderedAccessView* unorderedAccessView; D3D11_MAPPED_SUBRESOURCE mapped; int num_elements; int element_bytesize; + bool computable; ID3D11DeviceContext* lastContext; unsigned char* read_data; #ifdef _XBOX_ONE diff --git a/Vulkan/PlatformStructuredBuffer.cpp b/Vulkan/PlatformStructuredBuffer.cpp index fef917e7..417f9c8b 100644 --- a/Vulkan/PlatformStructuredBuffer.cpp +++ b/Vulkan/PlatformStructuredBuffer.cpp @@ -11,6 +11,7 @@ PlatformStructuredBuffer::PlatformStructuredBuffer() ,last_offset(0) ,buffer(nullptr) ,mCpuRead(false) + ,mSetCPUData(false) ,mLastFrame(0) ,mFrameIndex(0) { @@ -71,9 +72,6 @@ void PlatformStructuredBuffer::AddPerFrameBuffer(const void *init_data) usageFlags|=vk::BufferUsageFlagBits::eTransferSrc; int buffer_aligned_size=mSlots*kBufferAlign; int alloc_size=buffer_aligned_size*mMaxApplyCount; - vk::BufferCreateInfo buf_info = vk::BufferCreateInfo() - .setSize(alloc_size) - .setUsage(vk::BufferUsageFlagBits::eStorageBuffer); vk::Device *vulkanDevice = ((vulkan::RenderPlatform *)renderPlatform)->AsVulkanDevice(); perFrameBuffers.push_back(PerFrameBuffer()); PerFrameBuffer &perFrameBuffer=perFrameBuffers.back(); @@ -133,6 +131,8 @@ void PlatformStructuredBuffer::SetData(crossplatform::DeviceContext& deviceConte if(!buffer) buffer = new unsigned char[mTotalSize]; memcpy(buffer,data,mTotalSize); + + mSetCPUData = true; } } @@ -184,7 +184,7 @@ void PlatformStructuredBuffer::ActualApply(crossplatform::DeviceContext &deviceC } last_offset =(kBufferAlign * mSlots) * mCurApplyCount; - if (!as_uav && buffer) + if ((!as_uav && buffer) || mSetCPUData) { uint8_t *pData = nullptr; vmaMapMemory(lastBuffer->mAllocationInfo.allocator, lastBuffer->mAllocationInfo.allocation, (void**)&pData); @@ -195,6 +195,8 @@ void PlatformStructuredBuffer::ActualApply(crossplatform::DeviceContext &deviceC vmaUnmapMemory(lastBuffer->mAllocationInfo.allocator, lastBuffer->mAllocationInfo.allocation); } mCurApplyCount++; + + mSetCPUData = false; } } diff --git a/Vulkan/PlatformStructuredBuffer.h b/Vulkan/PlatformStructuredBuffer.h index 629692e7..1b0c2ea6 100644 --- a/Vulkan/PlatformStructuredBuffer.h +++ b/Vulkan/PlatformStructuredBuffer.h @@ -24,6 +24,7 @@ namespace platform virtual ~PlatformStructuredBuffer(); void RestoreDeviceObjects(crossplatform::RenderPlatform *r, int count, int unit_size, bool computable, bool cpu_read, void *init_data,const char *name, crossplatform::ResourceUsageFrequency bufferUsageHint) override; + void AddPerFrameBuffer(const void *init_data); void* GetBuffer(crossplatform::DeviceContext &deviceContext) override; const void* OpenReadBuffer(crossplatform::DeviceContext &deviceContext) override; void CloseReadBuffer(crossplatform::DeviceContext &deviceContext) override; @@ -37,9 +38,9 @@ namespace platform void ActualApply(crossplatform::DeviceContext &,bool) override; - size_t GetLastOffset(); - vk::Buffer *GetLastBuffer(); - size_t GetSize(); + size_t GetLastOffset(); + vk::Buffer* GetLastBuffer(); + size_t GetSize(); private: //! Total allocated size for each buffer static const int mBufferSize = 1024 * 64 * 8; @@ -76,9 +77,9 @@ namespace platform int mMaxApplyMod = 1; unsigned char * buffer; bool mCpuRead; - void AddPerFrameBuffer(const void *init_data); + bool mSetCPUData; uint64_t mLastFrame; - int mFrameIndex; + int mFrameIndex; }; } }