gfxD3D11VertexBuffer.cpp
Engine/source/gfx/D3D11/gfxD3D11VertexBuffer.cpp
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2015 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "gfx/D3D11/gfxD3D11VertexBuffer.h" 26#include "console/console.h" 27 28GFXD3D11VertexBuffer::~GFXD3D11VertexBuffer() 29{ 30 if(getOwningDevice() != NULL) 31 { 32 if(mBufferType != GFXBufferTypeVolatile) 33 { 34 SAFE_RELEASE(vb); 35 } 36 } 37} 38 39void GFXD3D11VertexBuffer::lock(U32 vertexStart, U32 vertexEnd, void **vertexPtr) 40{ 41 PROFILE_SCOPE(GFXD3D11VertexBuffer_lock); 42 43 AssertFatal(lockedVertexStart == 0 && lockedVertexEnd == 0, "Cannot lock a buffer more than once!"); 44 45 D3D11_MAP flags = D3D11_MAP_WRITE_DISCARD; 46 47 switch(mBufferType) 48 { 49 case GFXBufferTypeStatic: 50 case GFXBufferTypeDynamic: 51 flags = D3D11_MAP_WRITE_DISCARD; 52 break; 53 54 case GFXBufferTypeVolatile: 55 56 // Get or create the volatile buffer... 57 mVolatileBuffer = D3D11->findVBPool( &mVertexFormat, vertexEnd ); 58 59 if( !mVolatileBuffer ) 60 mVolatileBuffer = D3D11->createVBPool( &mVertexFormat, mVertexSize ); 61 62 vb = mVolatileBuffer->vb; 63 64 // Get our range now... 65 AssertFatal(vertexStart == 0, "Cannot get a subrange on a volatile buffer."); 66 AssertFatal(vertexEnd <= GFX_MAX_DYNAMIC_VERTS, "Cannot get more than GFX_MAX_DYNAMIC_VERTS in a volatile buffer. Up the constant!"); 67 AssertFatal(mVolatileBuffer->lockedVertexStart == 0 && mVolatileBuffer->lockedVertexEnd == 0, "Got more than one lock on the volatile pool."); 68 69 // We created the pool when we requested this volatile buffer, so assume it exists... 70 if( mVolatileBuffer->mNumVerts + vertexEnd > GFX_MAX_DYNAMIC_VERTS ) 71 { 72 flags = D3D11_MAP_WRITE_DISCARD; 73 mVolatileStart = vertexStart = 0; 74 vertexEnd = vertexEnd; 75 } 76 else 77 { 78 flags = D3D11_MAP_WRITE_NO_OVERWRITE; 79 mVolatileStart = vertexStart = mVolatileBuffer->mNumVerts; 80 vertexEnd += mVolatileBuffer->mNumVerts; 81 } 82 83 mVolatileBuffer->mNumVerts = vertexEnd+1; 84 85 mVolatileBuffer->lockedVertexStart = vertexStart; 86 mVolatileBuffer->lockedVertexEnd = vertexEnd; 87 break; 88 } 89 90 lockedVertexStart = vertexStart; 91 lockedVertexEnd = vertexEnd; 92 93 // uncomment it for debugging purpose. called many times per frame... spammy! 94 //Con::printf("%x: Locking %s range (%d, %d)", this, (mBufferType == GFXBufferTypeVolatile ? "volatile" : "static"), lockedVertexStart, lockedVertexEnd); 95 96 U32 sizeToLock = (vertexEnd - vertexStart) * mVertexSize; 97 if(mBufferType == GFXBufferTypeStatic) 98 { 99 *vertexPtr = new U8[sizeToLock]; 100 mLockedBuffer = *vertexPtr; 101 } 102 else 103 { 104 D3D11_MAPPED_SUBRESOURCE pVertexData; 105 ZeroMemory(&pVertexData, sizeof(D3D11_MAPPED_SUBRESOURCE)); 106 107 HRESULT hr = D3D11DEVICECONTEXT->Map(vb, 0, flags, 0, &pVertexData); 108 109 if(FAILED(hr)) 110 { 111 AssertFatal(false, "Unable to lock vertex buffer."); 112 } 113 114 *vertexPtr = (U8*)pVertexData.pData + (vertexStart * mVertexSize); 115 } 116 117 118 119 #ifdef TORQUE_DEBUG 120 121 // Allocate a debug buffer large enough for the lock 122 // plus space for over and under run guard strings. 123 const U32 guardSize = sizeof( _VBGuardString ); 124 mDebugGuardBuffer = new U8[sizeToLock+(guardSize*2)]; 125 126 // Setup the guard strings. 127 dMemcpy( mDebugGuardBuffer, _VBGuardString, guardSize ); 128 dMemcpy( mDebugGuardBuffer + sizeToLock + guardSize, _VBGuardString, guardSize ); 129 130 // Store the real lock pointer and return our debug pointer. 131 mLockedBuffer = *vertexPtr; 132 *vertexPtr = mDebugGuardBuffer + guardSize; 133 134 #endif // TORQUE_DEBUG 135} 136 137void GFXD3D11VertexBuffer::unlock() 138{ 139 PROFILE_SCOPE(GFXD3D11VertexBuffer_unlock); 140 141 #ifdef TORQUE_DEBUG 142 143 if ( mDebugGuardBuffer ) 144 { 145 const U32 guardSize = sizeof( _VBGuardString ); 146 const U32 sizeLocked = (lockedVertexEnd - lockedVertexStart) * mVertexSize; 147 148 // First check the guard areas for overwrites. 149 AssertFatal(dMemcmp( mDebugGuardBuffer, _VBGuardString, guardSize) == 0, 150 "GFXD3D11VertexBuffer::unlock - Caught lock memory underrun!" ); 151 AssertFatal(dMemcmp( mDebugGuardBuffer + sizeLocked + guardSize, _VBGuardString, guardSize) == 0, 152 "GFXD3D11VertexBuffer::unlock - Caught lock memory overrun!" ); 153 154 // Copy the debug content down to the real VB. 155 dMemcpy(mLockedBuffer, mDebugGuardBuffer + guardSize, sizeLocked); 156 157 // Cleanup. 158 delete [] mDebugGuardBuffer; 159 mDebugGuardBuffer = NULL; 160 //mLockedBuffer = NULL; 161 } 162 163 #endif // TORQUE_DEBUG 164 165 if(mBufferType == GFXBufferTypeStatic) 166 { 167 const U32 sizeLocked = (lockedVertexEnd - lockedVertexStart) * mVertexSize; 168 //set up the update region of the buffer 169 D3D11_BOX box; 170 box.back = 1; 171 box.front = 0; 172 box.top = 0; 173 box.bottom = 1; 174 box.left = lockedVertexStart * mVertexSize; 175 box.right = lockedVertexEnd * mVertexSize; 176 //update the real vb buffer 177 D3D11DEVICECONTEXT->UpdateSubresource(vb, 0, &box,mLockedBuffer,sizeLocked, 0); 178 //clean up the old buffer 179 delete[] mLockedBuffer; 180 mLockedBuffer = NULL; 181 } 182 else 183 { 184 D3D11DEVICECONTEXT->Unmap(vb,0); 185 } 186 187 188 mIsFirstLock = false; 189 190 //uncomment it for debugging purpose. called many times per frame... spammy! 191 //Con::printf("%x: Unlocking %s range (%d, %d)", this, (mBufferType == GFXBufferTypeVolatile ? "volatile" : "static"), lockedVertexStart, lockedVertexEnd); 192 193 lockedVertexEnd = lockedVertexStart = 0; 194 195 if(mVolatileBuffer.isValid()) 196 { 197 mVolatileBuffer->lockedVertexStart = 0; 198 mVolatileBuffer->lockedVertexEnd = 0; 199 mVolatileBuffer = NULL; 200 } 201} 202 203void GFXD3D11VertexBuffer::zombify() 204{ 205 AssertFatal(lockedVertexStart == 0 && lockedVertexEnd == 0, "GFXD3D11VertexBuffer::zombify - Cannot zombify a locked buffer!"); 206 // Static buffers are managed by D3D11 so we don't deal with them. 207 if(mBufferType == GFXBufferTypeDynamic) 208 { 209 SAFE_RELEASE(vb); 210 } 211} 212 213void GFXD3D11VertexBuffer::resurrect() 214{ 215 // Static buffers are managed by D3D11 so we don't deal with them. 216 if(mBufferType == GFXBufferTypeDynamic) 217 { 218 D3D11_BUFFER_DESC desc; 219 desc.ByteWidth = mVertexSize * mNumVerts; 220 desc.Usage = D3D11_USAGE_DYNAMIC; 221 desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 222 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 223 desc.MiscFlags = 0; 224 desc.StructureByteStride = 0; 225 226 HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &vb); 227 228 if(FAILED(hr)) 229 { 230 AssertFatal(false, "GFXD3D11VertexBuffer::resurrect - Failed to allocate VB"); 231 } 232 } 233} 234 235