From 63e10f3357d77bec9765878b451cca4eece7a343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Sat, 15 Aug 2015 18:07:43 -0700 Subject: [PATCH] D3D11: Fixed compute image mip selection. --- examples/common/bgfx_utils.cpp | 6 +- src/bgfx.cpp | 18 ++--- src/bgfx_p.h | 27 +++++++- src/renderer_d3d.h | 112 ++++++++++++++++++++++-------- src/renderer_d3d11.cpp | 120 +++++++++++++++++++++++++++++++-- src/renderer_d3d11.h | 1 + src/renderer_d3d12.cpp | 5 +- 7 files changed, 238 insertions(+), 51 deletions(-) diff --git a/examples/common/bgfx_utils.cpp b/examples/common/bgfx_utils.cpp index b874e6a0b..e9c56ea5e 100644 --- a/examples/common/bgfx_utils.cpp +++ b/examples/common/bgfx_utils.cpp @@ -131,7 +131,11 @@ bgfx::ShaderHandle loadShader(const char* _name) bgfx::ProgramHandle loadProgram(bx::FileReaderI* _reader, const char* _vsName, const char* _fsName) { bgfx::ShaderHandle vsh = loadShader(_reader, _vsName); - bgfx::ShaderHandle fsh = loadShader(_reader, _fsName); + bgfx::ShaderHandle fsh = BGFX_INVALID_HANDLE; + if (NULL != _fsName) + { + fsh = loadShader(_reader, _fsName); + } return bgfx::createProgram(vsh, fsh, true /* destroy shaders when program is destroyed */); } diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 072f43393..f0332bc20 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -2507,28 +2507,18 @@ again: ProgramHandle createProgram(ShaderHandle _vsh, ShaderHandle _fsh, bool _destroyShaders) { BGFX_CHECK_MAIN_THREAD(); - ProgramHandle handle = s_ctx->createProgram(_vsh, _fsh); - - if (_destroyShaders) + if (!isValid(_fsh) ) { - destroyShader(_vsh); - destroyShader(_fsh); + return createProgram(_vsh, _destroyShaders); } - return handle; + return s_ctx->createProgram(_vsh, _fsh, _destroyShaders); } ProgramHandle createProgram(ShaderHandle _csh, bool _destroyShader) { BGFX_CHECK_MAIN_THREAD(); - ProgramHandle handle = s_ctx->createProgram(_csh); - - if (_destroyShader) - { - destroyShader(_csh); - } - - return handle; + return s_ctx->createProgram(_csh, _destroyShader); } void destroyProgram(ProgramHandle _handle) diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 60029d1c8..1d75ef873 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -2603,6 +2603,7 @@ namespace bgfx sr.m_refCount = 1; sr.m_hash = iohash; sr.m_num = 0; + sr.m_owned = false; sr.m_uniforms = NULL; UniformHandle* uniforms = (UniformHandle*)alloca(count*sizeof(UniformHandle) ); @@ -2682,6 +2683,16 @@ namespace bgfx shaderDecRef(_handle); } + void shaderTakeOwnership(ShaderHandle _handle) + { + ShaderRef& sr = m_shaderRef[_handle.idx]; + if (!sr.m_owned) + { + sr.m_owned = true; + shaderDecRef(_handle); + } + } + void shaderIncRef(ShaderHandle _handle) { ShaderRef& sr = m_shaderRef[_handle.idx]; @@ -2712,7 +2723,7 @@ namespace bgfx } } - BGFX_API_FUNC(ProgramHandle createProgram(ShaderHandle _vsh, ShaderHandle _fsh) ) + BGFX_API_FUNC(ProgramHandle createProgram(ShaderHandle _vsh, ShaderHandle _fsh, bool _destroyShaders) ) { if (!isValid(_vsh) || !isValid(_fsh) ) @@ -2749,10 +2760,16 @@ namespace bgfx cmdbuf.write(_fsh); } + if (_destroyShaders) + { + shaderTakeOwnership(_vsh); + shaderTakeOwnership(_fsh); + } + return handle; } - BGFX_API_FUNC(ProgramHandle createProgram(ShaderHandle _vsh) ) + BGFX_API_FUNC(ProgramHandle createProgram(ShaderHandle _vsh, bool _destroyShader) ) { if (!isValid(_vsh) ) { @@ -2779,6 +2796,11 @@ namespace bgfx cmdbuf.write(fsh); } + if (_destroyShader) + { + shaderTakeOwnership(_vsh); + } + return handle; } @@ -3564,6 +3586,7 @@ namespace bgfx uint32_t m_hash; int16_t m_refCount; uint16_t m_num; + bool m_owned; }; struct ProgramRef diff --git a/src/renderer_d3d.h b/src/renderer_d3d.h index 99f50babd..d2882ae38 100644 --- a/src/renderer_d3d.h +++ b/src/renderer_d3d.h @@ -100,15 +100,15 @@ namespace bgfx class StateCacheT { public: - void add(uint64_t _id, Ty* _item) + void add(uint64_t _key, Ty* _value) { - invalidate(_id); - m_hashMap.insert(stl::make_pair(_id, _item) ); + invalidate(_key); + m_hashMap.insert(stl::make_pair(_key, _value) ); } - Ty* find(uint64_t _id) + Ty* find(uint64_t _key) { - typename HashMap::iterator it = m_hashMap.find(_id); + typename HashMap::iterator it = m_hashMap.find(_key); if (it != m_hashMap.end() ) { return it->second; @@ -117,9 +117,9 @@ namespace bgfx return NULL; } - void invalidate(uint64_t _id) + void invalidate(uint64_t _key) { - typename HashMap::iterator it = m_hashMap.find(_id); + typename HashMap::iterator it = m_hashMap.find(_key); if (it != m_hashMap.end() ) { DX_RELEASE_WARNONLY(it->second, 0); @@ -151,15 +151,15 @@ namespace bgfx class StateCache { public: - void add(uint64_t _id, uint16_t _item) + void add(uint64_t _key, uint16_t _value) { - invalidate(_id); - m_hashMap.insert(stl::make_pair(_id, _item) ); + invalidate(_key); + m_hashMap.insert(stl::make_pair(_key, _value) ); } - uint16_t find(uint64_t _id) + uint16_t find(uint64_t _key) { - HashMap::iterator it = m_hashMap.find(_id); + HashMap::iterator it = m_hashMap.find(_key); if (it != m_hashMap.end() ) { return it->second; @@ -168,9 +168,9 @@ namespace bgfx return UINT16_MAX; } - void invalidate(uint64_t _id) + void invalidate(uint64_t _key) { - HashMap::iterator it = m_hashMap.find(_id); + HashMap::iterator it = m_hashMap.find(_key); if (it != m_hashMap.end() ) { m_hashMap.erase(it); @@ -196,33 +196,28 @@ namespace bgfx class StateCacheLru { public: - void add(uint64_t _hash, Ty _value) + void add(uint64_t _key, Ty _value, uint16_t _parent) { uint16_t handle = m_alloc.alloc(); if (UINT16_MAX == handle) { uint16_t back = m_alloc.getBack(); - m_alloc.free(back); - HashMap::iterator it = m_hashMap.find(m_data[back].m_hash); - if (it != m_hashMap.end() ) - { - m_hashMap.erase(it); - } - + invalidate(back); handle = m_alloc.alloc(); } BX_CHECK(UINT16_MAX != handle, "Failed to find handle."); Data& data = m_data[handle]; - data.m_hash = _hash; - data.m_value = _value; - m_hashMap.insert(stl::make_pair(_hash, handle) ); + data.m_hash = _key; + data.m_value = _value; + data.m_parent = _parent; + m_hashMap.insert(stl::make_pair(_key, handle) ); } - Ty* find(uint64_t _hash) + Ty* find(uint64_t _key) { - HashMap::iterator it = m_hashMap.find(_hash); + HashMap::iterator it = m_hashMap.find(_key); if (it != m_hashMap.end() ) { uint16_t handle = it->second; @@ -233,8 +228,59 @@ namespace bgfx return NULL; } + void invalidate(uint64_t _key) + { + HashMap::iterator it = m_hashMap.find(_key); + if (it != m_hashMap.end() ) + { + uint16_t handle = it->second; + m_alloc.free(_handle); + m_hashMap.erase(it); + release(m_data[handle].m_value); + } + } + + void invalidate(uint16_t _handle) + { + if (m_alloc.isValid(_handle) ) + { + m_alloc.free(_handle); + Data& data = m_data[_handle]; + m_hashMap.erase(m_hashMap.find(data.m_hash) ); + release(data.m_value); + } + } + + void invalidateWithParent(uint16_t _parent) + { + for (uint32_t ii = 0; ii < m_alloc.getNumHandles();) + { + uint16_t handle = m_alloc.getHandleAt(ii); + Data& data = m_data[handle]; + + if (data.m_parent == _parent) + { + m_alloc.free(handle); + Data& data = m_data[handle]; + m_hashMap.erase(m_hashMap.find(data.m_hash) ); + release(data.m_value); + } + else + { + ++ii; + } + } + } + void invalidate() { + for (uint32_t ii = 0, num = m_alloc.getNumHandles(); ii < num; ++ii) + { + uint16_t handle = m_alloc.getHandleAt(ii); + Data& data = m_data[handle]; + release(data.m_value); + } + m_hashMap.clear(); m_alloc.reset(); } @@ -244,6 +290,17 @@ namespace bgfx return uint32_t(m_hashMap.size() ); } + template + void release(Ty) + { + } + + template<> + void release(IUnknown* _ptr) + { + DX_RELEASE(_ptr, 0); + } + private: typedef stl::unordered_map HashMap; HashMap m_hashMap; @@ -252,6 +309,7 @@ namespace bgfx { uint64_t m_hash; Ty m_value; + uint16_t m_parent; }; Data m_data[MaxHandleT]; diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 0d3b7ca81..718e7f87d 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -680,7 +680,7 @@ namespace bgfx { namespace d3d11 uint32_t flags = 0 | D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_BGRA_SUPPORT -// | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS + | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS | (BX_ENABLED(BGFX_CONFIG_DEBUG) ? D3D11_CREATE_DEVICE_DEBUG : 0) ; @@ -1777,6 +1777,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); m_depthStencilStateCache.invalidate(); m_rasterizerStateCache.invalidate(); m_samplerStateCache.invalidate(); + m_srvUavLru.invalidate(); } void invalidateCompute() @@ -2394,6 +2395,101 @@ BX_PRAGMA_DIAGNOSTIC_POP(); commitTextureStage(); } + ID3D11UnorderedAccessView* getCachedUav(TextureHandle _handle, uint8_t _mip) + { + bx::HashMurmur2A murmur; + murmur.begin(); + murmur.add(_handle); + murmur.add(_mip); + murmur.add(0); + uint32_t hash = murmur.end(); + + IUnknown** ptr = m_srvUavLru.find(hash); + ID3D11UnorderedAccessView* uav; + if (NULL == ptr) + { + TextureD3D11& texture = m_textures[_handle.idx]; + + D3D11_UNORDERED_ACCESS_VIEW_DESC desc; + desc.Format = s_textureFormat[texture.m_textureFormat].m_fmtSrv; + switch (texture.m_type) + { + case TextureD3D11::Texture2D: + case TextureD3D11::TextureCube: + desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipSlice = _mip; + break; + + case TextureD3D11::Texture3D: + desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; + desc.Texture3D.MipSlice = _mip; + desc.Texture3D.FirstWSlice = 0; + desc.Texture3D.WSize = 1; + break; + } + + DX_CHECK(m_device->CreateUnorderedAccessView(texture.m_ptr, &desc, &uav) ); + + m_srvUavLru.add(hash, uav, _handle.idx); + } + else + { + uav = static_cast(*ptr); + } + + return uav; + } + + ID3D11ShaderResourceView* getCachedSrv(TextureHandle _handle, uint8_t _mip) + { + bx::HashMurmur2A murmur; + murmur.begin(); + murmur.add(_handle); + murmur.add(_mip); + murmur.add(0); + uint32_t hash = murmur.end(); + + IUnknown** ptr = m_srvUavLru.find(hash); + ID3D11ShaderResourceView* srv; + if (NULL == ptr) + { + TextureD3D11& texture = m_textures[_handle.idx]; + + D3D11_SHADER_RESOURCE_VIEW_DESC desc; + desc.Format = s_textureFormat[texture.m_textureFormat].m_fmtSrv; + switch (texture.m_type) + { + case TextureD3D11::Texture2D: + desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + desc.Texture2D.MostDetailedMip = _mip; + desc.Texture2D.MipLevels = 1; + break; + + case TextureD3D11::TextureCube: + desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + desc.TextureCube.MostDetailedMip = _mip; + desc.TextureCube.MipLevels = 1; + break; + + case TextureD3D11::Texture3D: + desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + desc.Texture3D.MostDetailedMip = _mip; + desc.Texture3D.MipLevels = 1; + break; + } + + DX_CHECK(m_device->CreateShaderResourceView(texture.m_ptr, &desc, &srv) ); + + m_srvUavLru.add(hash, srv, _handle.idx); + } + else + { + srv = static_cast(*ptr); + } + + return srv; + } + void ovrPostReset() { #if BGFX_CONFIG_USE_OVR @@ -2838,6 +2934,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); StateCacheT m_inputLayoutCache; StateCacheT m_rasterizerStateCache; StateCacheT m_samplerStateCache; + StateCacheLru m_srvUavLru; TextVideoMem m_textVideoMem; @@ -3307,7 +3404,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); const bool swizzle = TextureFormat::BGRA8 == m_textureFormat && 0 != (m_flags&BGFX_TEXTURE_COMPUTE_WRITE); BX_TRACE("Texture %3d: %s (requested: %s), %dx%d%s%s%s." - , this - s_renderD3D11->m_textures + , getHandle() , getName( (TextureFormat::Enum)m_textureFormat) , getName( (TextureFormat::Enum)m_requestedFormat) , textureWidth @@ -3504,6 +3601,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); void TextureD3D11::destroy() { + s_renderD3D11->m_srvUavLru.invalidateWithParent(getHandle().idx); DX_RELEASE(m_srv, 0); DX_RELEASE(m_uav, 0); DX_RELEASE(m_ptr, 0); @@ -3560,6 +3658,12 @@ BX_PRAGMA_DIAGNOSTIC_POP(); { } + TextureHandle TextureD3D11::getHandle() const + { + TextureHandle handle = { (uint16_t)(this - s_renderD3D11->m_textures) }; + return handle; + } + void FrameBufferD3D11::create(uint8_t _num, const TextureHandle* _handles) { for (uint32_t ii = 0; ii < BX_COUNTOF(m_rtv); ++ii) @@ -4074,14 +4178,20 @@ BX_PRAGMA_DIAGNOSTIC_POP(); { case Binding::Image: { - const TextureD3D11& texture = m_textures[bind.m_idx]; + TextureD3D11& texture = m_textures[bind.m_idx]; if (Access::Read != bind.m_un.m_compute.m_access) { - uav[ii] = texture.m_uav; + uav[ii] = 0 == bind.m_un.m_compute.m_mip + ? texture.m_uav + : s_renderD3D11->getCachedUav(texture.getHandle(), bind.m_un.m_compute.m_mip) + ; } else { - srv[ii] = texture.m_srv; + srv[ii] = 0 == bind.m_un.m_compute.m_mip + ? texture.m_srv + : s_renderD3D11->getCachedSrv(texture.getHandle(), bind.m_un.m_compute.m_mip) + ; sampler[ii] = texture.m_sampler; } } diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index d8ced4a63..fec302a62 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -284,6 +284,7 @@ namespace bgfx { namespace d3d11 void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); void commit(uint8_t _stage, uint32_t _flags = BGFX_SAMPLER_DEFAULT_FLAGS); void resolve(); + TextureHandle getHandle() const; union { diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index 438dff26d..4e533f61a 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -2589,7 +2589,8 @@ data.NumQualityLevels = 0; { default: case D3D12_UAV_DIMENSION_TEXTURE2D: - uavd->Texture2D.MipSlice = _mip; + uavd->Texture2D.MipSlice = _mip; + uavd->Texture2D.PlaneSlice = 0; break; case D3D12_UAV_DIMENSION_TEXTURE3D: @@ -4111,7 +4112,7 @@ data.NumQualityLevels = 0; m_commandList->SetGraphicsRootDescriptorTable(Rdt::SRV, srvHandle[0]); - bindLru.add(bindHash, srvHandle[0]); + bindLru.add(bindHash, srvHandle[0], 0); } } else