D3D11: Fixed compute image mip selection.

This commit is contained in:
Branimir Karadžić 2015-08-15 18:07:43 -07:00
parent 0670b98700
commit 63e10f3357
7 changed files with 238 additions and 51 deletions

View File

@ -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 */);
}

View File

@ -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)

View File

@ -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

View File

@ -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<typename Ty>
void release(Ty)
{
}
template<>
void release<IUnknown*>(IUnknown* _ptr)
{
DX_RELEASE(_ptr, 0);
}
private:
typedef stl::unordered_map<uint64_t, uint16_t> 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];

View File

@ -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<ID3D11UnorderedAccessView*>(*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<ID3D11ShaderResourceView*>(*ptr);
}
return srv;
}
void ovrPostReset()
{
#if BGFX_CONFIG_USE_OVR
@ -2838,6 +2934,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
StateCacheT<ID3D11InputLayout> m_inputLayoutCache;
StateCacheT<ID3D11RasterizerState> m_rasterizerStateCache;
StateCacheT<ID3D11SamplerState> m_samplerStateCache;
StateCacheLru<IUnknown*, 1024> 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;
}
}

View File

@ -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
{

View File

@ -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