gfxD3D11PrimitiveBuffer.cpp
Engine/source/gfx/D3D11/gfxD3D11PrimitiveBuffer.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 "gfx/D3D11/gfxD3D11Device.h" 25#include "gfx/D3D11/gfxD3D11EnumTranslate.h" 26#include "gfx/D3D11/gfxD3D11PrimitiveBuffer.h" 27#include "core/util/safeRelease.h" 28 29void GFXD3D11PrimitiveBuffer::prepare() 30{ 31 D3D11->_setPrimitiveBuffer(this); 32} 33 34void GFXD3D11PrimitiveBuffer::lock(U32 indexStart, U32 indexEnd, void **indexPtr) 35{ 36 AssertFatal(!mLocked, "GFXD3D11PrimitiveBuffer::lock - Can't lock a primitive buffer more than once!"); 37 38 mLocked = true; 39 D3D11_MAP flags = D3D11_MAP_WRITE_DISCARD; 40 41 switch(mBufferType) 42 { 43 case GFXBufferTypeImmutable: 44 case GFXBufferTypeStatic: 45 case GFXBufferTypeDynamic: 46 flags = D3D11_MAP_WRITE_DISCARD; 47 break; 48 49 case GFXBufferTypeVolatile: 50 // Get our range now... 51 AssertFatal(indexStart == 0, "Cannot get a subrange on a volatile buffer."); 52 AssertFatal(indexEnd < GFX_MAX_DYNAMIC_INDICES, "Cannot get more than GFX_MAX_DYNAMIC_INDICES in a volatile buffer. Up the constant!"); 53 54 // Get the primtive buffer 55 mVolatileBuffer = D3D11->mDynamicPB; 56 57 AssertFatal( mVolatileBuffer, "GFXD3D11PrimitiveBuffer::lock - No dynamic primitive buffer was available!"); 58 59 // We created the pool when we requested this volatile buffer, so assume it exists... 60 if(mVolatileBuffer->mIndexCount + indexEnd > GFX_MAX_DYNAMIC_INDICES) 61 { 62 flags = D3D11_MAP_WRITE_DISCARD; 63 mVolatileStart = indexStart = 0; 64 indexEnd = indexEnd; 65 } 66 else 67 { 68 flags = D3D11_MAP_WRITE_NO_OVERWRITE; 69 mVolatileStart = indexStart = mVolatileBuffer->mIndexCount; 70 indexEnd += mVolatileBuffer->mIndexCount; 71 } 72 73 mVolatileBuffer->mIndexCount = indexEnd + 1; 74 ib = mVolatileBuffer->ib; 75 76 break; 77 } 78 79 80 mIndexStart = indexStart; 81 mIndexEnd = indexEnd; 82 83 if (mBufferType == GFXBufferTypeStatic || mBufferType == GFXBufferTypeImmutable) 84 { 85 U32 sizeToLock = (indexEnd - indexStart) * sizeof(U16); 86 *indexPtr = new U8[sizeToLock]; 87 mLockedBuffer = *indexPtr; 88 } 89 else 90 { 91 D3D11_MAPPED_SUBRESOURCE pIndexData; 92 ZeroMemory(&pIndexData, sizeof(D3D11_MAPPED_SUBRESOURCE)); 93 94 HRESULT hr = D3D11DEVICECONTEXT->Map(ib, 0, flags, 0, &pIndexData); 95 96 if(FAILED(hr)) 97 { 98 AssertFatal(false, "GFXD3D11PrimitiveBuffer::lock - Could not lock primitive buffer."); 99 } 100 101 *indexPtr = (U8*)pIndexData.pData + (indexStart * sizeof(U16)) ; 102 } 103 104 #ifdef TORQUE_DEBUG 105 106 // Allocate a debug buffer large enough for the lock 107 // plus space for over and under run guard strings. 108 mLockedSize = (indexEnd - indexStart) * sizeof(U16); 109 const U32 guardSize = sizeof( _PBGuardString ); 110 mDebugGuardBuffer = new U8[mLockedSize+(guardSize*2)]; 111 112 // Setup the guard strings. 113 dMemcpy( mDebugGuardBuffer, _PBGuardString, guardSize ); 114 dMemcpy( mDebugGuardBuffer + mLockedSize + guardSize, _PBGuardString, guardSize ); 115 116 // Store the real lock pointer and return our debug pointer. 117 mLockedBuffer = *indexPtr; 118 *indexPtr = (U16*)( mDebugGuardBuffer + guardSize ); 119 120 #endif // TORQUE_DEBUG 121} 122 123void GFXD3D11PrimitiveBuffer::unlock() 124{ 125 #ifdef TORQUE_DEBUG 126 127 if ( mDebugGuardBuffer ) 128 { 129 const U32 guardSize = sizeof( _PBGuardString ); 130 131 // First check the guard areas for overwrites. 132 AssertFatal( dMemcmp( mDebugGuardBuffer, _PBGuardString, guardSize ) == 0, 133 "GFXD3D11PrimitiveBuffer::unlock - Caught lock memory underrun!" ); 134 AssertFatal( dMemcmp( mDebugGuardBuffer + mLockedSize + guardSize, _PBGuardString, guardSize ) == 0, 135 "GFXD3D11PrimitiveBuffer::unlock - Caught lock memory overrun!" ); 136 137 // Copy the debug content down to the real PB. 138 dMemcpy( mLockedBuffer, mDebugGuardBuffer + guardSize, mLockedSize ); 139 140 // Cleanup. 141 delete [] mDebugGuardBuffer; 142 mDebugGuardBuffer = NULL; 143 //mLockedBuffer = NULL; 144 mLockedSize = 0; 145 } 146 147 #endif // TORQUE_DEBUG 148 149 const U32 totalSize = this->mIndexCount * sizeof(U16); 150 151 if (mBufferType == GFXBufferTypeStatic || mBufferType == GFXBufferTypeImmutable) 152 { 153 //set up the update region of the buffer 154 D3D11_BOX box; 155 box.back = 1; 156 box.front = 0; 157 box.top = 0; 158 box.bottom =1; 159 box.left = mIndexStart *sizeof(U16); 160 box.right = mIndexEnd * sizeof(U16); 161 //update the real ib buffer 162 D3D11DEVICECONTEXT->UpdateSubresource(ib, 0, &box,mLockedBuffer,totalSize, 0); 163 //clean up the old buffer 164 delete[] mLockedBuffer; 165 mLockedBuffer = NULL; 166 } 167 else 168 { 169 D3D11DEVICECONTEXT->Unmap(ib,0); 170 } 171 172 mLocked = false; 173 mIsFirstLock = false; 174 mVolatileBuffer = NULL; 175} 176 177GFXD3D11PrimitiveBuffer::~GFXD3D11PrimitiveBuffer() 178{ 179 if( mBufferType != GFXBufferTypeVolatile ) 180 { 181 SAFE_RELEASE(ib); 182 } 183} 184 185void GFXD3D11PrimitiveBuffer::zombify() 186{ 187 if (mBufferType == GFXBufferTypeStatic || mBufferType == GFXBufferTypeImmutable) 188 return; 189 190 AssertFatal(!mLocked, "GFXD3D11PrimitiveBuffer::zombify - Cannot zombify a locked buffer!"); 191 192 if (mBufferType == GFXBufferTypeVolatile) 193 { 194 // We must null the volatile buffer else we're holding 195 // a dead pointer which can be set on the device. 196 ib = NULL; 197 return; 198 } 199 200 // Dynamic buffers get released. 201 SAFE_RELEASE(ib); 202} 203 204void GFXD3D11PrimitiveBuffer::resurrect() 205{ 206 if ( mBufferType != GFXBufferTypeDynamic ) 207 return; 208 209 D3D11_BUFFER_DESC desc; 210 desc.ByteWidth = sizeof(U16) * mIndexCount; 211 desc.Usage = D3D11_USAGE_DYNAMIC; 212 desc.BindFlags = D3D11_BIND_INDEX_BUFFER; 213 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 214 desc.MiscFlags = 0; 215 desc.StructureByteStride = 0; 216 217 HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &ib); 218 219 if(FAILED(hr)) 220 { 221 AssertFatal(false, "GFXD3D11PrimitiveBuffer::resurrect - Failed to allocate an index buffer."); 222 } 223} 224