1414#include " CAdditionalVertexStreamManager.h"
1515#include " CVertexStreamBoundingBoxManager.h"
1616
17- #include < algorithm>
18- #include < array>
19- #include < cstring>
20- #include < new>
21-
2217// ///////////////////////////////////////////////////////////
2318//
2419// CProxyDirect3DVertexBuffer::CProxyDirect3DVertexBuffer
@@ -114,50 +109,40 @@ HRESULT CProxyDirect3DVertexBuffer::Lock(UINT OffsetToLock, UINT SizeToLock, voi
114109 CVertexStreamBoundingBoxManager::GetSingleton ()->OnVertexBufferRangeInvalidated (m_pOriginal, OffsetToLock, SizeToLock);
115110 }
116111
117- ClearFallbackLock ();
118-
119112 *ppbData = NULL ;
113+ HRESULT hr = DoLock (OffsetToLock, SizeToLock, ppbData, Flags);
114+ HRESULT originalHr = hr;
120115
121- const UINT clampedSize = ClampLockSize (OffsetToLock, SizeToLock);
122-
123- HRESULT hr = DoLock (OffsetToLock, clampedSize, ppbData, Flags);
124- if (SUCCEEDED (hr) && *ppbData != NULL )
125- return hr;
126-
127- HRESULT recoveryHr = TryRecoverLock (OffsetToLock, clampedSize, ppbData, Flags, hr);
128- if (SUCCEEDED (recoveryHr) && *ppbData != NULL )
129- return recoveryHr;
130-
131- HRESULT finalHr = FAILED (recoveryHr) ? recoveryHr : hr;
132- HRESULT fallbackHr = ActivateFallbackLock (OffsetToLock, clampedSize, ppbData, Flags, finalHr);
133- if (SUCCEEDED (fallbackHr) && *ppbData != NULL )
134- return fallbackHr;
135-
136- if (FAILED (fallbackHr))
137- finalHr = fallbackHr;
138-
139- struct
116+ if (SUCCEEDED (hr) && *ppbData == NULL )
140117 {
141- const char * szText;
142- uint uiReportId;
143- uint uiLogEventId;
144- } info;
145- if (finalHr == D3D_OK)
146- info = {" result NULL" , 8621 , 621 };
147- else if (finalHr == STATUS_ARRAY_BOUNDS_EXCEEDED)
148- info = {" offset out of range" , 8622 , 622 };
149- else if (finalHr == STATUS_ACCESS_VIOLATION)
150- info = {" access violation" , 8623 , 623 };
151- else
152- info = {" fail" , 8620 , 620 };
118+ hr = D3DERR_INVALIDCALL;
119+ }
153120
154- SString strMessage (" Lock VertexBuffer [%s] hr:%x Length:%x Usage:%x FVF:%x Pool:%x OffsetToLock:%x SizeToLock:%x Flags:%x" , info.szText , finalHr, m_iMemUsed,
155- m_dwUsage, m_dwFVF, m_pool, OffsetToLock, clampedSize, Flags);
156- WriteDebugEvent (strMessage);
157- AddReportLog (info.uiReportId , strMessage);
158- CCore::GetSingleton ().LogEvent (info.uiLogEventId , " Lock VertexBuffer" , " " , strMessage);
121+ // Report problems
122+ if (FAILED (hr))
123+ {
124+ struct
125+ {
126+ const char * szText;
127+ uint uiReportId;
128+ uint uiLogEventId;
129+ } info;
130+ if (hr == D3DERR_INVALIDCALL && originalHr == D3D_OK)
131+ info = {" result NULL" , 8621 , 621 };
132+ else if (hr == STATUS_ARRAY_BOUNDS_EXCEEDED)
133+ info = {" offset out of range" , 8622 , 622 };
134+ else if (hr == STATUS_ACCESS_VIOLATION)
135+ info = {" access violation" , 8623 , 623 };
136+ else
137+ info = {" fail" , 8620 , 620 };
159138
160- return finalHr;
139+ SString strMessage (" Lock VertexBuffer [%s] hr:%x origHr:%x Length:%x Usage:%x FVF:%x Pool:%x OffsetToLock:%x SizeToLock:%x Flags:%x" , info.szText , hr,
140+ originalHr, m_iMemUsed, m_dwUsage, m_dwFVF, m_pool, OffsetToLock, SizeToLock, Flags);
141+ WriteDebugEvent (strMessage);
142+ AddReportLog (info.uiReportId , strMessage);
143+ CCore::GetSingleton ().LogEvent (info.uiLogEventId , " Lock VertexBuffer" , " " , strMessage);
144+ }
145+ return hr;
161146}
162147
163148// ///////////////////////////////////////////////////////////
@@ -169,197 +154,22 @@ HRESULT CProxyDirect3DVertexBuffer::Lock(UINT OffsetToLock, UINT SizeToLock, voi
169154// ///////////////////////////////////////////////////////////
170155HRESULT CProxyDirect3DVertexBuffer::DoLock (UINT OffsetToLock, UINT SizeToLock, void ** ppbData, DWORD Flags)
171156{
172- if (OffsetToLock >= m_iMemUsed)
173- return STATUS_ARRAY_BOUNDS_EXCEEDED;
174-
175- UINT adjustedSize = ClampLockSize (OffsetToLock, SizeToLock);
176- if (adjustedSize == 0 )
177- return STATUS_ARRAY_BOUNDS_EXCEEDED;
178-
179- return LockInternal (OffsetToLock, adjustedSize, ppbData, Flags);
180- }
181-
182- HRESULT CProxyDirect3DVertexBuffer::Unlock ()
183- {
184- if (!m_fallbackLock.active )
185- return m_pOriginal->Unlock ();
186-
187- HRESULT copyHr = D3D_OK;
188-
189- if ((m_fallbackLock.flags & D3DLOCK_READONLY) == 0 && m_fallbackLock.size > 0 && !m_fallbackLock.buffer .empty ())
157+ // Validate sizes because gta can give invalid values (reason unknown)
158+ if (OffsetToLock + SizeToLock > m_iMemUsed)
190159 {
191- void * pDestination = NULL ;
192- copyHr = LockInternal (m_fallbackLock.offset , m_fallbackLock.size , &pDestination, 0 );
193- if (SUCCEEDED (copyHr) && pDestination != NULL )
160+ if (OffsetToLock > m_iMemUsed)
194161 {
195- std::memcpy (pDestination, m_fallbackLock.buffer .data (), m_fallbackLock.size );
196- HRESULT unlockHr = m_pOriginal->Unlock ();
197- if (FAILED (unlockHr))
198- {
199- copyHr = unlockHr;
200- SString strMessage (" Unlock VertexBuffer [fallback unlock failed] hr:%x Length:%x Usage:%x FVF:%x Pool:%x Offset:%x Size:%x" , unlockHr, m_iMemUsed,
201- m_dwUsage, m_dwFVF, m_pool, m_fallbackLock.offset , m_fallbackLock.size );
202- WriteDebugEvent (strMessage);
203- AddReportLog (8627 , strMessage);
204- CCore::GetSingleton ().LogEvent (627 , " Unlock VertexBuffer" , " " , strMessage);
205- }
206- }
207- else
208- {
209- if (SUCCEEDED (copyHr) && pDestination == NULL )
210- copyHr = D3DERR_INVALIDCALL;
211-
212- SString strMessage (" Unlock VertexBuffer [fallback copy failed] hr:%x Length:%x Usage:%x FVF:%x Pool:%x Offset:%x Size:%x" , copyHr, m_iMemUsed, m_dwUsage,
213- m_dwFVF, m_pool, m_fallbackLock.offset , m_fallbackLock.size );
214- WriteDebugEvent (strMessage);
215- AddReportLog (8626 , strMessage);
216- CCore::GetSingleton ().LogEvent (626 , " Unlock VertexBuffer" , " " , strMessage);
162+ return STATUS_ARRAY_BOUNDS_EXCEEDED;
217163 }
164+ SizeToLock = m_iMemUsed - OffsetToLock;
218165 }
219166
220- ClearFallbackLock ();
221- return D3D_OK;
222- }
223-
224- UINT CProxyDirect3DVertexBuffer::ClampLockSize (UINT OffsetToLock, UINT SizeToLock) const
225- {
226- if (OffsetToLock >= m_iMemUsed)
227- return 0 ;
228-
229- const UINT available = static_cast <UINT>(m_iMemUsed - OffsetToLock);
230- if (available == 0 )
231- return 0 ;
232-
233- if (SizeToLock == 0 )
234- return available;
235-
236- return std::min (SizeToLock, available);
237- }
238-
239- HRESULT CProxyDirect3DVertexBuffer::LockInternal (UINT OffsetToLock, UINT SizeToLock, void ** ppbData, DWORD Flags)
240- {
241- if (ppbData == NULL )
242- return E_INVALIDARG;
243-
244- *ppbData = NULL ;
245-
246167 __try
247168 {
248169 return m_pOriginal->Lock (OffsetToLock, SizeToLock, ppbData, Flags);
249170 }
250171 __except (GetExceptionCode () == EXCEPTION_ACCESS_VIOLATION)
251172 {
252- *ppbData = NULL ;
253173 return STATUS_ACCESS_VIOLATION;
254174 }
255175}
256-
257- HRESULT CProxyDirect3DVertexBuffer::TryRecoverLock (UINT OffsetToLock, UINT SizeToLock, void ** ppbData, DWORD Flags, HRESULT originalHr)
258- {
259- HRESULT lastHr = originalHr;
260-
261- struct SLockAttempt
262- {
263- DWORD flags;
264- UINT offset;
265- UINT size;
266- bool adjustPointer;
267- };
268-
269- std::array<SLockAttempt, 7 > attempts = {
270- SLockAttempt{Flags & ~D3DLOCK_DONOTWAIT, OffsetToLock, SizeToLock, false },
271- SLockAttempt{Flags & ~D3DLOCK_NOOVERWRITE, OffsetToLock, SizeToLock, false },
272- SLockAttempt{Flags & ~D3DLOCK_DISCARD, OffsetToLock, SizeToLock, false },
273- SLockAttempt{Flags & ~(D3DLOCK_DONOTWAIT | D3DLOCK_NOOVERWRITE), OffsetToLock, SizeToLock, false },
274- SLockAttempt{Flags & ~(D3DLOCK_DONOTWAIT | D3DLOCK_NOOVERWRITE | D3DLOCK_NO_DIRTY_UPDATE), OffsetToLock, SizeToLock, false },
275- SLockAttempt{0u , OffsetToLock, SizeToLock, false },
276- SLockAttempt{0u , 0u , static_cast <UINT>(m_iMemUsed), true },
277- };
278-
279- for (const SLockAttempt& attempt : attempts)
280- {
281- if (attempt.flags == Flags && attempt.offset == OffsetToLock && attempt.size == SizeToLock)
282- continue ;
283-
284- if (attempt.size > m_iMemUsed)
285- continue ;
286-
287- UINT clampedSize = ClampLockSize (attempt.offset , attempt.size );
288- if (clampedSize == 0 )
289- continue ;
290-
291- void * pRecovered = NULL ;
292- HRESULT hr = LockInternal (attempt.offset , clampedSize, &pRecovered, attempt.flags );
293- if (SUCCEEDED (hr) && pRecovered != NULL )
294- {
295- if (attempt.adjustPointer )
296- {
297- UINT pointerOffset = 0 ;
298- if (OffsetToLock > attempt.offset )
299- pointerOffset = OffsetToLock - attempt.offset ;
300- if (pointerOffset >= clampedSize)
301- {
302- lastHr = hr;
303- continue ;
304- }
305- pRecovered = static_cast <void *>(static_cast <std::uint8_t *>(pRecovered) + pointerOffset);
306- }
307-
308- *ppbData = pRecovered;
309-
310- SString strMessage (" Lock VertexBuffer [retry] hr:%x->%x Length:%x Usage:%x FVF:%x Pool:%x Offset:%x Size:%x Flags:%x->%x" , originalHr, hr, m_iMemUsed,
311- m_dwUsage, m_dwFVF, m_pool, OffsetToLock, SizeToLock, Flags, attempt.flags );
312- WriteDebugEvent (strMessage);
313- AddReportLog (8625 , strMessage);
314- CCore::GetSingleton ().LogEvent (625 , " Lock VertexBuffer" , " " , strMessage);
315-
316- return hr;
317- }
318-
319- lastHr = hr;
320- }
321-
322- return lastHr;
323- }
324-
325- HRESULT CProxyDirect3DVertexBuffer::ActivateFallbackLock (UINT OffsetToLock, UINT SizeToLock, void ** ppbData, DWORD Flags, HRESULT originalHr)
326- {
327- if (ppbData == NULL )
328- return originalHr;
329-
330- UINT clampedSize = ClampLockSize (OffsetToLock, SizeToLock);
331- if (clampedSize == 0 )
332- return originalHr;
333-
334- try
335- {
336- m_fallbackLock.buffer .resize (clampedSize);
337- }
338- catch (const std::bad_alloc&)
339- {
340- return E_OUTOFMEMORY;
341- }
342-
343- m_fallbackLock.active = true ;
344- m_fallbackLock.offset = OffsetToLock;
345- m_fallbackLock.size = clampedSize;
346- m_fallbackLock.flags = Flags;
347-
348- *ppbData = m_fallbackLock.buffer .data ();
349-
350- SString strMessage (" Lock VertexBuffer [fallback] hr:%x Length:%x Usage:%x FVF:%x Pool:%x OffsetToLock:%x SizeToLock:%x Flags:%x" , originalHr, m_iMemUsed,
351- m_dwUsage, m_dwFVF, m_pool, OffsetToLock, clampedSize, Flags);
352- WriteDebugEvent (strMessage);
353- AddReportLog (8624 , strMessage);
354- CCore::GetSingleton ().LogEvent (624 , " Lock VertexBuffer" , " " , strMessage);
355-
356- return D3D_OK;
357- }
358-
359- void CProxyDirect3DVertexBuffer::ClearFallbackLock ()
360- {
361- m_fallbackLock.active = false ;
362- m_fallbackLock.offset = 0 ;
363- m_fallbackLock.size = 0 ;
364- m_fallbackLock.flags = 0 ;
365- }
0 commit comments