diff options
author | Jose Fonseca <jfonseca@vmware.com> | 2016-05-05 17:01:12 +0100 |
---|---|---|
committer | Jose Fonseca <jfonseca@vmware.com> | 2016-05-05 20:32:27 +0100 |
commit | 5057d100cfc3763c422a15023dbdb6778502d552 (patch) | |
tree | 4a1a68e462662c10f04553ee1ce600f1a0be609b /wrappers | |
parent | 1ee7c4cfceb11c667da9327bdb61a1921fff384e (diff) |
dxgitrace: Try to detect non-overlapping buffer writes.
Diffstat (limited to 'wrappers')
-rw-r--r-- | wrappers/dxgitrace.hpp | 129 | ||||
-rw-r--r-- | wrappers/dxgitrace.py | 34 |
2 files changed, 154 insertions, 9 deletions
diff --git a/wrappers/dxgitrace.hpp b/wrappers/dxgitrace.hpp new file mode 100644 index 00000000..526ac609 --- /dev/null +++ b/wrappers/dxgitrace.hpp @@ -0,0 +1,129 @@ +/************************************************************************** + * + * Copyright 2014 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +/* + * Helper functions for C++ code generated by dxgitrace.py. + * + */ + +#pragma once + + +#include <assert.h> + +#include "d3dcommonshader.hpp" + +#include "d3d10imports.hpp" +#include "d3d10size.hpp" +#include "d3d11imports.hpp" +#include "d3d11size.hpp" +#include "dcompimports.hpp" +#include "d2dimports.hpp" // WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT +#include "d3d9imports.hpp" // D3DPERF_* +#include "memtrace.hpp" + + +/* + * Overloaded function to determine whether a given resource be have maps + * shadowed or not. + */ + +inline bool +_shouldShadowMap(IDXGISurface *pSurface) +{ + return false; +} + +inline bool +_shouldShadowMap(ID3D10Resource *pResource) +{ + D3D10_RESOURCE_DIMENSION Type = D3D10_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&Type); + return Type == D3D10_RESOURCE_DIMENSION_BUFFER; +} + +inline bool +_shouldShadowMap(ID3D11Resource *pResource) +{ + D3D11_RESOURCE_DIMENSION Type = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&Type); + return Type == D3D11_RESOURCE_DIMENSION_BUFFER; +} + + +/* + * Overloaded function to initialize buffer resources upon creation time. + */ + +inline void +_initializeBuffer(ID3D10Device *pDevice, const D3D10_BUFFER_DESC *pDesc, ID3D10Buffer *pBuffer) +{ + HRESULT hr; + + if (!(pDesc->CPUAccessFlags & D3D10_CPU_ACCESS_WRITE)) { + return; + } + + assert(pBuffer); + + D3D10_MAP MapType = pDesc->Usage == D3D10_USAGE_DYNAMIC ? D3D10_MAP_WRITE_DISCARD : D3D10_MAP_WRITE; + VOID *pData; + hr = pBuffer->Map(MapType, 0, &pData); + assert(SUCCEEDED(hr)); + if (FAILED(hr)) { + return; + } + + MemoryShadow::zero(pData, pDesc->ByteWidth); + pBuffer->Unmap(); +} + +inline void +_initializeBuffer(ID3D11Device *pDevice, const D3D11_BUFFER_DESC *pDesc, ID3D11Buffer *pBuffer) +{ + HRESULT hr; + + if (!(pDesc->CPUAccessFlags & D3D11_CPU_ACCESS_WRITE)) { + return; + } + + assert(pBuffer); + + com_ptr<ID3D11DeviceContext> pImmediateContext; + pDevice->GetImmediateContext(&pImmediateContext); + assert(pImmediateContext); + + D3D11_MAP MapType = pDesc->Usage == D3D11_USAGE_DYNAMIC ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE; + D3D11_MAPPED_SUBRESOURCE MappedResource; + hr = pImmediateContext->Map(pBuffer, 0, MapType, 0, &MappedResource); + assert(SUCCEEDED(hr)); + if (FAILED(hr)) { + return; + } + + MemoryShadow::zero(MappedResource.pData, pDesc->ByteWidth); + pImmediateContext->Unmap(pBuffer, 0); +} diff --git a/wrappers/dxgitrace.py b/wrappers/dxgitrace.py index fd1275d3..f3ea82d2 100644 --- a/wrappers/dxgitrace.py +++ b/wrappers/dxgitrace.py @@ -99,10 +99,12 @@ class D3DCommonTracer(DllTracer): if interface.hasBase(*self.mapInterfaces): variables += [ ('_MAP_DESC', 'm_MapDesc', None), + ('MemoryShadow', 'm_MapShadow', None), ] if interface.hasBase(d3d11.ID3D11DeviceContext): variables += [ ('std::map< std::pair<ID3D11Resource *, UINT>, _MAP_DESC >', 'm_MapDescs', None), + ('std::map< std::pair<ID3D11Resource *, UINT>, MemoryShadow >', 'm_MapShadows', None), ] return variables @@ -118,12 +120,20 @@ class D3DCommonTracer(DllTracer): resourceArg = method.getArgByName('pResource') if resourceArg is None: print ' _MAP_DESC & _MapDesc = m_MapDesc;' + print ' MemoryShadow & _MapShadow = m_MapShadow;' + print ' %s *pResourceInstance = m_pInstance;' % interface.name else: print ' _MAP_DESC & _MapDesc = m_MapDescs[std::pair<%s, UINT>(pResource, Subresource)];' % resourceArg.type + print ' MemoryShadow & _MapShadow = m_MapShadows[std::pair<%s, UINT>(pResource, Subresource)];' % resourceArg.type + print ' Wrap%spResourceInstance = static_cast<Wrap%s>(%s);' % (resourceArg.type, resourceArg.type, resourceArg.name) if method.name == 'Unmap': print ' if (_MapDesc.Size && _MapDesc.pData) {' + print ' if (_shouldShadowMap(pResourceInstance)) {' + print ' _MapShadow.update(trace::fakeMemcpy);' + print ' } else {' self.emit_memcpy('_MapDesc.pData', '_MapDesc.Size') + print ' }' print ' }' DllTracer.implementWrapperInterfaceMethodBody(self, interface, base, method) @@ -132,6 +142,13 @@ class D3DCommonTracer(DllTracer): # NOTE: recursive locks are explicitely forbidden print ' if (SUCCEEDED(_result)) {' print ' _getMapDesc(_this, %s, _MapDesc);' % ', '.join(method.argNames()) + print ' if (_MapDesc.pData && _shouldShadowMap(pResourceInstance)) {' + if interface.name.startswith('IDXGI'): + print ' (void)_MapShadow;' + else: + print ' bool _discard = MapType == 4 /* D3D1[01]_MAP_WRITE_DISCARD */;' + print ' _MapShadow.cover(_MapDesc.pData, _MapDesc.Size, _discard);' + print ' }' print ' } else {' print ' _MapDesc.pData = NULL;' print ' _MapDesc.Size = 0;' @@ -156,6 +173,13 @@ class D3DCommonTracer(DllTracer): print r' os::log("apitrace: warning: hiding IWarpPrivateAPI interface\n");' print r' }' + # Ensure buffers are initialized, otherwise we can fail to detect + # changes when unititialized data matches what the app wrote. + if method.name == 'CreateBuffer': + print r' if (SUCCEEDED(_result) && !pInitialData) {' + print r' _initializeBuffer(_this, pDesc, *ppBuffer);' + print r' }' + if __name__ == '__main__': print r'#include "guids_defs.hpp"' @@ -163,15 +187,7 @@ if __name__ == '__main__': print r'#include "trace_writer_local.hpp"' print r'#include "os.hpp"' print - print r'#include "d3dcommonshader.hpp"' - print - print r'#include "d3d10imports.hpp"' - print r'#include "d3d10size.hpp"' - print r'#include "d3d11imports.hpp"' - print r'#include "d3d11size.hpp"' - print r'#include "dcompimports.hpp"' - print r'#include "d2dimports.hpp" // WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT' - print r'#include "d3d9imports.hpp" // D3DPERF_*' + print r'#include "dxgitrace.hpp"' print api = API() |