diff options
| author | chai <chaifix@163.com> | 2019-08-14 22:50:43 +0800 | 
|---|---|---|
| committer | chai <chaifix@163.com> | 2019-08-14 22:50:43 +0800 | 
| commit | 15740faf9fe9fe4be08965098bbf2947e096aeeb (patch) | |
| tree | a730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/GfxDevice/d3d11/D3D11VBO.cpp | |
Diffstat (limited to 'Runtime/GfxDevice/d3d11/D3D11VBO.cpp')
| -rw-r--r-- | Runtime/GfxDevice/d3d11/D3D11VBO.cpp | 1193 | 
1 files changed, 1193 insertions, 0 deletions
| diff --git a/Runtime/GfxDevice/d3d11/D3D11VBO.cpp b/Runtime/GfxDevice/d3d11/D3D11VBO.cpp new file mode 100644 index 0000000..e0beaf1 --- /dev/null +++ b/Runtime/GfxDevice/d3d11/D3D11VBO.cpp @@ -0,0 +1,1193 @@ +#include "UnityPrefix.h" +#include "D3D11VBO.h" +#include "D3D11Context.h" +#include "Runtime/GfxDevice/GfxDevice.h" +#include "Runtime/Graphics/TriStripper.h" +#include "Runtime/GfxDevice/ChannelAssigns.h" +#include "Runtime/Utilities/ArrayUtility.h" +#include "D3D11Utils.h" + + + +// defined in GfxDeviceD3D11.cpp +ID3D11InputLayout* GetD3D11VertexDeclaration (const ChannelInfoArray& channels); +void UpdateChannelBindingsD3D11 (const ChannelAssigns& channels); + +ID3D11InputLayout* g_ActiveInputLayoutD3D11; +D3D11_PRIMITIVE_TOPOLOGY g_ActiveTopologyD3D11 = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; + + + +static const D3D11_PRIMITIVE_TOPOLOGY kTopologyD3D11[kPrimitiveTypeCount] = +{ +	D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, +	D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, +	D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, +	D3D11_PRIMITIVE_TOPOLOGY_LINELIST, +	D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, +	D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, +}; + +static const D3D11_PRIMITIVE_TOPOLOGY kTopologyD3D11Tess[kPrimitiveTypeCount] = +{ +	D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST, +	D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED, +	D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST, +	D3D11_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST, +	D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED, +	D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST, +}; + + +void SetInputLayoutD3D11 (ID3D11DeviceContext* ctx, ID3D11InputLayout* layout) +{ +	if (g_ActiveInputLayoutD3D11 != layout) +	{ +		g_ActiveInputLayoutD3D11 = layout; +		D3D11_CALL (ctx->IASetInputLayout (layout)); +	} +} + + +static ID3D11InputLayout* GetD3D11VertexDeclaration (UInt32 shaderChannelsMap) +{ +	ChannelInfoArray channels; +	int offset = 0; +	for (int i = 0; i < kShaderChannelCount; i++) +	{ +		ChannelInfo& info = channels[i]; +		if (shaderChannelsMap & (1 << i)) +		{ +			info.stream = 0; +			info.offset = offset; +			info.format = VBO::GetDefaultChannelFormat( i ); +			info.dimension = VBO::GetDefaultChannelDimension( i ); +			offset += VBO::GetDefaultChannelByteSize( i ); +		} +		else +			info.Reset(); +	} +	return GetD3D11VertexDeclaration (channels); +} + + +// ----------------------------------------------------------------------------- + +ID3D11Buffer* D3D11VBO::ms_CustomIB = NULL; +int	D3D11VBO::ms_CustomIBSize = 0; +UInt32 D3D11VBO::ms_CustomIBUsedBytes = 0; + +ID3D11Buffer* D3D11VBO::ms_AllWhiteBuffer = NULL; + + +D3D11VBO::D3D11VBO() +:	m_IB(NULL) +,	m_StagingIB(NULL) +,	m_IBReadable(NULL) +,	m_IBSize(0) +,	m_useForSO(false) +{ +	memset(m_VBStreams, 0, sizeof(m_VBStreams)); +	memset(m_StagingVB, 0, sizeof(m_StagingVB)); +} + +D3D11VBO::~D3D11VBO () +{ +	for (int s = 0; s < kMaxVertexStreams; ++s) +	{ +		//std::string tmp = GetDebugNameD3D11(m_StagingVB[s]); +		REGISTER_EXTERNAL_GFX_DEALLOCATION(m_VBStreams[s]); +		REGISTER_EXTERNAL_GFX_DEALLOCATION(m_StagingVB[s]); +		SAFE_RELEASE(m_VBStreams[s]); +		SAFE_RELEASE(m_StagingVB[s]); +	} +	if (m_IB) +	{ +		REGISTER_EXTERNAL_GFX_DEALLOCATION(m_IB); +		SAFE_RELEASE(m_IB); +	} +	if (m_StagingIB) +	{ +		REGISTER_EXTERNAL_GFX_DEALLOCATION(m_StagingIB); +		SAFE_RELEASE(m_StagingIB); +	} +	delete[] m_IBReadable; +} + + +static ID3D11Buffer* CreateStagingBuffer (int size) +{ +	ID3D11Device* dev = GetD3D11Device(); +	D3D11_BUFFER_DESC desc; +	desc.ByteWidth = size; +	desc.Usage = D3D11_USAGE_STAGING; +	desc.BindFlags = 0; +	desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; +	desc.MiscFlags = 0; +	desc.StructureByteStride = 0; + +	ID3D11Buffer* buffer = NULL; +	HRESULT hr = dev->CreateBuffer (&desc, NULL, &buffer); +	REGISTER_EXTERNAL_GFX_ALLOCATION_REF(buffer,size,NULL); +	AssertIf (FAILED(hr)); +	return buffer; +} + +void D3D11VBO::CleanupSharedBuffers() +{ +	REGISTER_EXTERNAL_GFX_DEALLOCATION(ms_CustomIB); +	REGISTER_EXTERNAL_GFX_DEALLOCATION(ms_AllWhiteBuffer); +	SAFE_RELEASE (ms_CustomIB); +	SAFE_RELEASE (ms_AllWhiteBuffer); +	ms_CustomIBSize = 0; +	ms_CustomIBUsedBytes = 0; +} + + +void D3D11VBO::UpdateVertexStream (const VertexBufferData& sourceData, unsigned stream) +{ +	DebugAssert (!m_IsStreamMapped[stream]); +	const StreamInfo& srcStream = sourceData.streams[stream]; +	const int oldSize = CalculateVertexStreamSize(m_Streams[stream], m_VertexCount); + +#if UNITY_METRO +			#pragma message("Fix ugly hack CreateStagingBuffer") +			// So honestly I don't how what's happening here, but when running on ARM (Surface) with Feature Level 9.1 and if we create a vertex buffer with size 144 +			// Sometimes we crash in D3D11VBO dtor in this line SAFE_RELEASE(m_StagingVB[s]); +			// Sometimes we get an access violation but sometimes it's Data misalignment exception like below +			// First-chance exception at 0x75499B2A (setupapi.dll) in Drift Mania Championship 2.exe: 0x80000002: Datatype misalignment +			// Repro case 495782 +			// Not reproducible on Win32 running Feature Level 9.1 + +			// In any case it seems increasing min size up to 256, solves this issue for now +			int newSize = CalculateVertexStreamSize(srcStream, sourceData.vertexCount); +			int addon = 1; +			while (newSize > 0 && newSize < 256) +			{ +				 newSize = CalculateVertexStreamSize(srcStream, sourceData.vertexCount + addon); +				 addon++; +			} + +#else +	const int newSize = CalculateVertexStreamSize(srcStream, sourceData.vertexCount); +#endif + + +	m_Streams[stream] = srcStream; +	if (newSize == 0) +	{ +		REGISTER_EXTERNAL_GFX_DEALLOCATION(m_VBStreams[stream]); +		REGISTER_EXTERNAL_GFX_DEALLOCATION(m_StagingVB[stream]); +		SAFE_RELEASE (m_VBStreams[stream]); +		SAFE_RELEASE (m_StagingVB[stream]); +		return; +	} + +	const bool isDynamic = (m_StreamModes[stream] == kStreamModeDynamic); +	const bool useStaging = !isDynamic; + +	if (m_VBStreams[stream] == NULL || newSize != oldSize) +	{ +		REGISTER_EXTERNAL_GFX_DEALLOCATION(m_VBStreams[stream]); +		REGISTER_EXTERNAL_GFX_DEALLOCATION(m_StagingVB[stream]); +		SAFE_RELEASE (m_VBStreams[stream]); +		SAFE_RELEASE (m_StagingVB[stream]); // release staging VB as well here + +		ID3D11Device* dev = GetD3D11Device(); +		D3D11_BUFFER_DESC desc; +		desc.ByteWidth = newSize; +		desc.Usage = isDynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; +		desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; +		if ( m_useForSO ) +			desc.BindFlags |= D3D11_BIND_STREAM_OUTPUT; +		desc.CPUAccessFlags = isDynamic ? D3D11_CPU_ACCESS_WRITE : 0; +		desc.MiscFlags = 0; +		desc.StructureByteStride = 0; +		HRESULT hr = dev->CreateBuffer (&desc, NULL, &m_VBStreams[stream]); +		REGISTER_EXTERNAL_GFX_ALLOCATION_REF(m_VBStreams[stream],newSize,this); +		if (FAILED(hr)) +		{ +			printf_console ("d3d11: failed to create vertex buffer of size %d [0x%X]\n", newSize, hr); +			return; +		} +		SetDebugNameD3D11 (m_VBStreams[stream], Format("VertexBuffer-%d", newSize)); + +		if (useStaging) +		{ +			m_StagingVB[stream] = CreateStagingBuffer (newSize); +			SetDebugNameD3D11 (m_StagingVB[stream], Format("StagingVertexBuffer-%d", newSize)); +		} +	} + +	// Don't update contents if there is no source data. +	// This is used to update the vertex declaration only, leaving buffer intact. +	// Also to create an empty buffer that is written to later. +	if (!sourceData.buffer) +		return; + +	HRESULT hr; + +	ID3D11Buffer* mapVB = NULL; +	D3D11_MAP mapType; + +	if (useStaging) +	{ +		mapVB = m_StagingVB[stream]; +		mapType = D3D11_MAP_WRITE; +	} +	else +	{ +		mapVB = m_VBStreams[stream]; +		mapType = D3D11_MAP_WRITE_DISCARD; +	} + +	Assert (mapVB); + +	ID3D11DeviceContext* ctx = GetD3D11Context(); + +	D3D11_MAPPED_SUBRESOURCE mapped; +	hr = ctx->Map (mapVB, 0, mapType, 0, &mapped); +	Assert (SUCCEEDED(hr)); +	CopyVertexStream (sourceData, reinterpret_cast<UInt8*>(mapped.pData), stream); +	ctx->Unmap (mapVB, 0); + +	if (useStaging) +		ctx->CopyResource (m_VBStreams[stream], m_StagingVB[stream]); +} + + +void D3D11VBO::UpdateIndexBufferData (const IndexBufferData& sourceData) +{ +	if( !sourceData.indices ) +	{ +		m_IBSize = 0; +		return; +	} + +	Assert (m_IB); +	HRESULT hr; + +	int size = sourceData.count * kVBOIndexSize; +	if (sourceData.hasTopologies & ((1<<kPrimitiveTriangleStripDeprecated) | (1<<kPrimitiveQuads))) +	{ +		delete[] m_IBReadable; +		m_IBReadable = new UInt16[sourceData.count]; +		memcpy (m_IBReadable, sourceData.indices, size); +	} + +	const D3D11_MAP mapType = m_IndicesDynamic ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE; +	ID3D11Buffer* mapIB; +	if (m_IndicesDynamic) +		mapIB = m_IB; +	else +	{ +		if (!m_StagingIB) +			m_StagingIB = CreateStagingBuffer(m_IBSize); +		mapIB = m_StagingIB; +	} + +	ID3D11DeviceContext* ctx = GetD3D11Context(); +	D3D11_MAPPED_SUBRESOURCE mapped; +	hr = ctx->Map (mapIB, 0, mapType, 0, &mapped); +	Assert (SUCCEEDED(hr)); + +	memcpy (mapped.pData, sourceData.indices, size); + +	ctx->Unmap (mapIB, 0); +	if (!m_IndicesDynamic) +		ctx->CopyResource (m_IB, m_StagingIB); +} + +bool D3D11VBO::MapVertexStream( VertexStreamData& outData, unsigned stream ) +{ +	if (m_VBStreams[stream] == NULL) +	{ +		printf_console ("d3d11: attempt to map null vertex buffer\n"); +		return false; +	} +	DebugAssert(!IsVertexBufferLost()); +	Assert(!m_IsStreamMapped[stream]); + +	const int vbSize = CalculateVertexStreamSize(m_Streams[stream], m_VertexCount); + +	const bool dynamic = (m_StreamModes[stream]==kStreamModeDynamic); + +	D3D11_MAPPED_SUBRESOURCE mapped; +	ID3D11Buffer* mapVB = dynamic ? m_VBStreams[stream] : m_StagingVB[stream]; +	D3D11_MAP mapType = dynamic ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE; +	HRESULT hr = GetD3D11Context()->Map (mapVB, 0, mapType, 0, &mapped); +	if( FAILED(hr) ) +	{ +		printf_console ("d3d11: failed to map vertex buffer %p of size %i [%x]\n", mapVB, vbSize, hr); +		return false; +	} +	m_IsStreamMapped[stream] = true; + +	UInt8* buffer = (UInt8*)mapped.pData; + +	outData.buffer = buffer; +	outData.channelMask = m_Streams[stream].channelMask; +	outData.stride = m_Streams[stream].stride; +	outData.vertexCount = m_VertexCount; + +	GetRealGfxDevice().GetFrameStats().AddUploadVBO(vbSize); + +	return true; +} + +void D3D11VBO::UnmapVertexStream (unsigned stream) +{ +	DebugAssert(m_VBStreams[stream]); +	Assert(m_IsStreamMapped[stream]); +	m_IsStreamMapped[stream] = false; +	ID3D11DeviceContext* ctx = GetD3D11Context(); + +	const bool dynamic = (m_StreamModes[stream]==kStreamModeDynamic); +	ID3D11Buffer* mapVB = dynamic ? m_VBStreams[stream] : m_StagingVB[stream]; +	ctx->Unmap (mapVB, 0); + +	if (!dynamic) +		ctx->CopyResource (m_VBStreams[stream], m_StagingVB[stream]); +} + +bool D3D11VBO::IsVertexBufferLost() const +{ +	for (int s = 0; s < kMaxVertexStreams; ++s) +		if (m_Streams[s].channelMask && !m_VBStreams[s]) +			return true; +	return false; +} + +int D3D11VBO::GetRuntimeMemorySize() const +{ +	int vertexSize = 0; +	for( int s = 0; s < kMaxVertexStreams; s++ ) +		vertexSize += m_Streams[s].stride; +	return vertexSize * m_VertexCount + m_IBSize; +} + + +bool SetTopologyD3D11 (GfxPrimitiveType topology, GfxDevice& device, ID3D11DeviceContext* ctx) +{ +	bool tessellation = device.IsShaderActive (kShaderHull) || device.IsShaderActive (kShaderDomain); +	D3D11_PRIMITIVE_TOPOLOGY topod3d = tessellation ? kTopologyD3D11Tess[topology] : kTopologyD3D11[topology]; +	if (topod3d == D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED) +		return false; + +	if (topod3d != g_ActiveTopologyD3D11) +	{ +		g_ActiveTopologyD3D11 = topod3d; +		D3D11_CALL (ctx->IASetPrimitiveTopology (topod3d)); +	} +	return true; +} + + +ID3D11Buffer* D3D11VBO::GetAllWhiteBuffer() +{ +	if (!ms_AllWhiteBuffer) +	{ +		int maxVerts = 0x10000; +		int size = maxVerts * sizeof(UInt32); +		UInt8* data = new UInt8[size]; +		memset (data, 0xFF, size); + +		D3D11_BUFFER_DESC desc; +		desc.ByteWidth = size; +		desc.Usage = D3D11_USAGE_IMMUTABLE; +		desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; +		desc.CPUAccessFlags = 0; +		desc.MiscFlags = 0; +		desc.StructureByteStride = 0; +		D3D11_SUBRESOURCE_DATA sdata; +		sdata.pSysMem = data; +		sdata.SysMemPitch = 0; +		sdata.SysMemSlicePitch = 0; +		HRESULT hr = GetD3D11Device()->CreateBuffer (&desc, &sdata, &ms_AllWhiteBuffer); +		REGISTER_EXTERNAL_GFX_ALLOCATION_REF(ms_AllWhiteBuffer,size,NULL); +		delete[] data; +	} +	return ms_AllWhiteBuffer; +} + + +void D3D11VBO::BindVertexStreams(GfxDevice& device, ID3D11DeviceContext* ctx, const ChannelAssigns& channels) +{ +	DX11_LOG_ENTER_FUNCTION("D3D11VBO::BindVertexStreams"); +	int freeStream = -1; +	for (int s = 0; s < kMaxVertexStreams; ++s) +	{ +		if (m_VBStreams[s]) +		{ +			UINT offset = 0; +			UINT stride = m_Streams[s].stride; +			D3D11_CALL (ctx->IASetVertexBuffers(s, 1, &m_VBStreams[s], &stride, &offset)); +		} +		else +			freeStream = s; +	} + +	UpdateChannelBindingsD3D11(channels); + +	device.BeforeDrawCall( false ); + +	const ChannelInfoArray* channelInfo = &m_ChannelInfo; +	if ((channels.GetSourceMap() & VERTEX_FORMAT1(Color)) && !m_ChannelInfo[kShaderChannelColor].IsValid()) +	{ +		if (freeStream != -1) +		{ +			static ChannelInfoArray colorChannelInfo; +			memcpy(&colorChannelInfo, m_ChannelInfo, sizeof(colorChannelInfo)); +			ChannelInfo& colorInfo = colorChannelInfo[kShaderChannelColor]; +			colorInfo.stream = freeStream; +			colorInfo.offset = 0; +			colorInfo.format = kChannelFormatColor; +			colorInfo.dimension = 1; +			channelInfo = &colorChannelInfo; +			ID3D11Buffer* whiteVB = GetAllWhiteBuffer(); +			UINT stride = 4; +			UINT offset = 0; +			D3D11_CALL (ctx->IASetVertexBuffers(freeStream, 1, &whiteVB, &stride, &offset)); +		} +		else +			ErrorString("Need a free stream to add default vertex colors!"); +	} +	ID3D11InputLayout* inputLayout = GetD3D11VertexDeclaration(m_ChannelInfo); +	SetInputLayoutD3D11 (ctx, inputLayout); +} + +void D3D11VBO::BindToStreamOutput() +{ +	const UINT offsets[] = { 0 }; +	GetD3D11Context()->SOSetTargets(1, m_VBStreams, offsets); +} + +void D3D11VBO::UnbindFromStreamOutput() +{ +	ID3D11Buffer* const buffers[] = { 0 }; +	const UINT offsets[] = { 0 }; +	GetD3D11Context()->SOSetTargets(1, buffers, offsets); +} + + +void D3D11VBO::DrawVBO (const ChannelAssigns& channels, UInt32 firstIndexByte, UInt32 indexCount, GfxPrimitiveType topology, UInt32 firstVertex, UInt32 vertexCount) +{ +	DX11_LOG_ENTER_FUNCTION("D3D11VBO::DrawVBO"); +	// just return if no indices +	if( m_IBSize == 0 ) +		return; + +	Assert(!m_IsStreamMapped[0]); +	if (m_VBStreams[0] == 0 || m_IB == 0) +	{ +		printf_console( "d3d: VB or IB is null\n" ); +		return; +	} + +	GfxDevice& device = GetRealGfxDevice(); +	ID3D11DeviceContext* ctx = GetD3D11Context(); +	BindVertexStreams (device, ctx, channels); + +	bool tessellation = device.IsShaderActive (kShaderHull) || device.IsShaderActive (kShaderDomain); +	if (tessellation && topology == kPrimitiveTriangleStripDeprecated) +	{ +		if (!m_IBReadable) +			return; + +		const UInt16* ibSrc = (const UInt16*)((const UInt8*)m_IBReadable + firstIndexByte); +		const int triCount = CountTrianglesInStrip (ibSrc, indexCount); + +		UInt32 ibBytesLocked; +		UInt16* ibPtr = MapDynamicIndexBuffer (triCount*3, ibBytesLocked); +		if (!ibPtr) +			return; +		Destripify (ibSrc, indexCount, ibPtr, triCount*3); +		UnmapDynamicIndexBuffer (); +		firstIndexByte = ms_CustomIBUsedBytes; +		ms_CustomIBUsedBytes += ibBytesLocked; +		D3D11_CALL (ctx->IASetIndexBuffer (ms_CustomIB, DXGI_FORMAT_R16_UINT, 0)); +		indexCount = ibBytesLocked/kVBOIndexSize; +		topology = kPrimitiveTriangles; +	} +	else if (topology == kPrimitiveQuads && !tessellation) +	{ +		if (!m_IBReadable) +			return; +		UInt32 ibBytesLocked; +		UInt16* ibPtr = MapDynamicIndexBuffer (indexCount/4*6, ibBytesLocked); +		if (!ibPtr) +			return; +		const UInt16* ibSrc = (const UInt16*)((const UInt8*)m_IBReadable + firstIndexByte); +		FillIndexBufferForQuads (ibPtr, ibBytesLocked, ibSrc, indexCount/4); +		UnmapDynamicIndexBuffer (); +		firstIndexByte = ms_CustomIBUsedBytes; +		ms_CustomIBUsedBytes += ibBytesLocked; +		D3D11_CALL (ctx->IASetIndexBuffer (ms_CustomIB, DXGI_FORMAT_R16_UINT, 0)); +		indexCount = ibBytesLocked/kVBOIndexSize; +	} +	else +	{ +		D3D11_CALL (ctx->IASetIndexBuffer (m_IB, DXGI_FORMAT_R16_UINT, 0)); +	} + +	// draw +	if (!SetTopologyD3D11 (topology, device, ctx)) +		return; +	D3D11_CALL (ctx->DrawIndexed (indexCount, firstIndexByte/2, 0)); +	device.GetFrameStats().AddDrawCall (GetPrimitiveCount(indexCount,topology,false), vertexCount); +	DX11_MARK_DRAWING(GetPrimitiveCount(indexCount,topology,false), vertexCount); + +} + +UInt16* D3D11VBO::MapDynamicIndexBuffer (int indexCount, UInt32& outBytesUsed) +{ +	HRESULT hr; +	const UInt32 maxIndices = 64000; +	Assert (indexCount <= maxIndices); +	indexCount = std::min<UInt32>(indexCount, maxIndices); + +	int ibCapacity = indexCount * kVBOIndexSize; +	int newIBSize = std::max (ibCapacity, 32*1024); // 32k IB at least + +	if (newIBSize > ms_CustomIBSize) +	{ +		if (ms_CustomIB) +		{ +			REGISTER_EXTERNAL_GFX_DEALLOCATION(ms_CustomIB); +			ms_CustomIB->Release(); +		} +		ms_CustomIBSize = newIBSize; +		ms_CustomIBUsedBytes = 0; + +		ID3D11Device* dev = GetD3D11Device(); + +		D3D11_BUFFER_DESC desc; +		desc.ByteWidth = newIBSize; +		desc.Usage = D3D11_USAGE_DYNAMIC; +		desc.BindFlags = D3D11_BIND_INDEX_BUFFER; +		desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; +		desc.MiscFlags = 0; +		desc.StructureByteStride = 0; +		hr = dev->CreateBuffer (&desc, NULL, &ms_CustomIB); +		REGISTER_EXTERNAL_GFX_ALLOCATION_REF(ms_CustomIB,newIBSize,NULL); +		if (FAILED(hr)) +		{ +			printf_console ("d3d11: failed to create custom index buffer of size %d [%x]\n", newIBSize, hr); +			return NULL; +		} +		SetDebugNameD3D11 (ms_CustomIB, Format("IndexBufferCustomDynamic-%d", newIBSize)); +	} + +	ID3D11DeviceContext* ctx = GetD3D11Context(); +	D3D11_MAPPED_SUBRESOURCE mapped; +	if (ms_CustomIBUsedBytes + ibCapacity > ms_CustomIBSize) +	{ +		hr = ctx->Map (ms_CustomIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped); +		if (FAILED(hr)) +		{ +			printf_console ("d3d11: failed to lock shared index buffer with discard [%x]\n", hr); +			return NULL; +		} +		ms_CustomIBUsedBytes = 0; +	}  +	else  +	{ +		hr = ctx->Map (ms_CustomIB, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped); +		if (FAILED(hr)) +		{ +			printf_console( "d3d11: failed to lock shared index buffer, offset %i size %i [%x]\n", ms_CustomIBUsedBytes, ibCapacity, hr); +			return NULL; +		} +	} +	outBytesUsed = ibCapacity; + +	return (UInt16*)((UInt8*)mapped.pData + ms_CustomIBUsedBytes); +} + +void D3D11VBO::UnmapDynamicIndexBuffer () +{ +	GetD3D11Context()->Unmap (ms_CustomIB, 0); +} + + +#if GFX_ENABLE_DRAW_CALL_BATCHING +void D3D11VBO::DrawCustomIndexed( const ChannelAssigns& channels, void* indices, UInt32 indexCount, +								 GfxPrimitiveType topology, UInt32 vertexRangeBegin, UInt32 vertexRangeEnd, UInt32 drawVertexCount ) +{ +	HRESULT hr; +	Assert (!m_IsStreamMapped[0]); + +	if (m_VBStreams[0] == 0) +	{ +		printf_console( "d3d11: VB is null\n" ); +		return; +	} + +	ID3D11DeviceContext* ctx = GetD3D11Context(); + +	UInt32 ibBytesUsed; +	UInt16* ibPtr = MapDynamicIndexBuffer (indexCount, ibBytesUsed); +	if (!ibPtr) +		return; +	memcpy (ibPtr, indices, ibBytesUsed); +	UnmapDynamicIndexBuffer (); + +	// draw +	GfxDevice& device = GetRealGfxDevice(); +	BindVertexStreams(device, ctx, channels); + +	D3D11_CALL (ctx->IASetIndexBuffer (ms_CustomIB, DXGI_FORMAT_R16_UINT, 0)); + +	// draw +	if (!SetTopologyD3D11 (topology, device, ctx)) +		return; +	D3D11_CALL (ctx->DrawIndexed (indexCount, ms_CustomIBUsedBytes / kVBOIndexSize, 0)); +	device.GetFrameStats().AddDrawCall (GetPrimitiveCount(indexCount,topology,false), drawVertexCount); + +	ms_CustomIBUsedBytes += ibBytesUsed; +} + +#endif // GFX_ENABLE_DRAW_CALL_BATCHING + + + +void D3D11VBO::UpdateVertexData( const VertexBufferData& buffer ) +{ +	for (unsigned stream = 0; stream < kMaxVertexStreams; stream++) +		UpdateVertexStream (buffer, stream); + +	memcpy (m_ChannelInfo, buffer.channels, sizeof(m_ChannelInfo)); +	m_VertexCount = buffer.vertexCount; +} + +void D3D11VBO::UpdateIndexData (const IndexBufferData& buffer) +{ +	int newSize = CalculateIndexBufferSize(buffer); + +	// If we have old buffer, but need different size: delete old one +	if (newSize != m_IBSize) +	{ +		if (m_IB) +		{ +			REGISTER_EXTERNAL_GFX_DEALLOCATION(m_IB); +			SAFE_RELEASE(m_IB); +		} +		if (m_StagingIB) +		{ +			REGISTER_EXTERNAL_GFX_DEALLOCATION(m_StagingIB); +			SAFE_RELEASE(m_StagingIB); +		} +	} + +	// Create buffer if we need to +	if (!m_IB) +	{ +		ID3D11Device* dev = GetD3D11Device(); +		D3D11_BUFFER_DESC desc; +		desc.ByteWidth = newSize; +		desc.Usage = m_IndicesDynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; +		desc.BindFlags = D3D11_BIND_INDEX_BUFFER; +		desc.CPUAccessFlags = m_IndicesDynamic ? D3D11_CPU_ACCESS_WRITE : 0; +		desc.MiscFlags = 0; +		desc.StructureByteStride = 0; +		HRESULT hr = dev->CreateBuffer (&desc, NULL, &m_IB); +		REGISTER_EXTERNAL_GFX_ALLOCATION_REF(m_IB,newSize,this); +		if( FAILED(hr) ) +		{ +			printf_console( "d3d11: failed to create index buffer of size %d [0x%X]\n", newSize, hr ); +			return; +		} +		SetDebugNameD3D11 (m_IB, Format("IndexBuffer-%d", newSize)); +	} + +	m_IBSize = newSize; +	UpdateIndexBufferData(buffer); +} + +void D3D11VBO::SetIndicesDynamic(bool dynamic) +{ +	// do nothing if a no-op +	if (dynamic == m_IndicesDynamic) +		return; + +	VBO::SetIndicesDynamic(dynamic); + +	// release current index buffers +	if (m_IB) +	{ +		REGISTER_EXTERNAL_GFX_DEALLOCATION(m_IB); +		SAFE_RELEASE(m_IB); +	} +	if (m_StagingIB) +	{ +		REGISTER_EXTERNAL_GFX_DEALLOCATION(m_StagingIB); +		SAFE_RELEASE(m_StagingIB); +	} +} + + + +// ----------------------------------------------------------------------------- + + +DynamicD3D11VBO::DynamicD3D11VBO( UInt32 vbSize, UInt32 ibSize ) +:	DynamicVBO() +,	m_VBSize(vbSize) +,	m_VBUsedBytes(0) +,	m_IBSize(ibSize) +,	m_IBUsedBytes(0) +,	m_VB(NULL) +,	m_IB(NULL) +,	m_LastChunkStartVertex(0) +,	m_LastChunkStartIndex(0) +,	m_QuadsIB(NULL) +{ +} + +DynamicD3D11VBO::~DynamicD3D11VBO () +{ +	if( m_VB ) { +		REGISTER_EXTERNAL_GFX_DEALLOCATION(m_VB); +		ULONG refCount = m_VB->Release(); +		AssertIf( refCount != 0 ); +	} +	if( m_IB ) { +		REGISTER_EXTERNAL_GFX_DEALLOCATION(m_IB); +		ULONG refCount = m_IB->Release(); +		AssertIf( refCount != 0 ); +	} +	if( m_QuadsIB ) { +		REGISTER_EXTERNAL_GFX_DEALLOCATION(m_QuadsIB); +		ULONG refCount = m_QuadsIB->Release(); +		AssertIf( refCount != 0 ); +	} +} + +void DynamicD3D11VBO::InitializeQuadsIB() +{ +	AssertIf( m_QuadsIB ); + +	const int kMaxQuads = 65536/4 - 4; // so we fit into 16 bit indices, minus some more just in case + +	UInt16* data = new UInt16[kMaxQuads*6]; +	UInt16* ib = data; +	UInt32 baseIndex = 0; +	for( int i = 0; i < kMaxQuads; ++i ) +	{ +		ib[0] = baseIndex + 1; +		ib[1] = baseIndex + 2; +		ib[2] = baseIndex; +		ib[3] = baseIndex + 2; +		ib[4] = baseIndex + 3; +		ib[5] = baseIndex; +		baseIndex += 4; +		ib += 6; +	} + +	ID3D11Device* dev = GetD3D11Device(); +	D3D11_BUFFER_DESC desc; +	desc.ByteWidth = kMaxQuads * 6 * kVBOIndexSize; +	desc.Usage = D3D11_USAGE_IMMUTABLE; +	desc.BindFlags = D3D11_BIND_INDEX_BUFFER; +	desc.CPUAccessFlags = 0; +	desc.MiscFlags = 0; +	desc.StructureByteStride = 0; +	D3D11_SUBRESOURCE_DATA srData; +	srData.pSysMem = data; +	srData.SysMemPitch = 0; +	srData.SysMemSlicePitch = 0; +	HRESULT hr = dev->CreateBuffer (&desc, &srData, &m_QuadsIB); +	REGISTER_EXTERNAL_GFX_ALLOCATION_REF(m_QuadsIB,desc.ByteWidth,this); +	delete[] data; +	if (FAILED(hr)) +	{ +		printf_console ("d3d11: failed to create quads index buffer [%x]\n", hr); +	} +	SetDebugNameD3D11 (m_QuadsIB, "IndexBufferQuads"); +} + + +void DynamicD3D11VBO::DrawChunk (const ChannelAssigns& channels) +{ +	DX11_LOG_ENTER_FUNCTION("DynamicD3D11VBO::DrawChunk"); +	// just return if nothing to render +	if( !m_LastChunkShaderChannelMask ) +		return; + +	HRESULT hr; + +	AssertIf( !m_LastChunkShaderChannelMask || !m_LastChunkStride ); +	AssertIf( m_LendedChunk ); + +	GfxDevice& device = GetRealGfxDevice(); +	ID3D11DeviceContext* ctx = GetD3D11Context(); + +	// setup VBO +	DebugAssert (m_VB); +	UINT strides = m_LastChunkStride; +	UINT offsets = 0; +	D3D11_CALL (ctx->IASetVertexBuffers(0, 1, &m_VB, &strides, &offsets)); + +	UpdateChannelBindingsD3D11(channels); +	device.BeforeDrawCall (false); + +	ID3D11InputLayout* inputLayout = GetD3D11VertexDeclaration (m_LastChunkShaderChannelMask); +	SetInputLayoutD3D11 (ctx, inputLayout); + +	// draw +	GfxDeviceStats& stats = device.GetFrameStats(); +	int primCount = 0; +	if (m_LastRenderMode == kDrawTriangleStrip) +	{ +		if (!SetTopologyD3D11(kPrimitiveTriangleStripDeprecated,device,ctx)) +			return; +		D3D11_CALL (ctx->Draw (m_LastChunkVertices, m_LastChunkStartVertex)); +		primCount = m_LastChunkVertices-2; +	} +	else if (m_LastRenderMode == kDrawIndexedTriangleStrip) +	{ +		DebugAssert (m_IB); +		if (!SetTopologyD3D11(kPrimitiveTriangleStripDeprecated,device,ctx)) +			return; +		D3D11_CALL (ctx->IASetIndexBuffer (m_IB, DXGI_FORMAT_R16_UINT, 0)); +		D3D11_CALL (ctx->DrawIndexed (m_LastChunkIndices, m_LastChunkStartIndex, m_LastChunkStartVertex)); +		primCount = m_LastChunkIndices-2; +	}	 +	else if( m_LastRenderMode == kDrawQuads ) +	{ +		if (!SetTopologyD3D11(kPrimitiveTriangles,device,ctx)) +			return; +		// initialize quads index buffer if needed +		if (!m_QuadsIB) +			InitializeQuadsIB(); +		// if quads index buffer has valid data, draw with it +		if (m_QuadsIB) +		{ +			D3D11_CALL (ctx->IASetIndexBuffer (m_QuadsIB, DXGI_FORMAT_R16_UINT, 0)); +			D3D11_CALL (ctx->DrawIndexed (m_LastChunkVertices/4*6, 0, m_LastChunkStartVertex)); +			primCount = m_LastChunkVertices/2; +		} +	} +	else if (m_LastRenderMode == kDrawIndexedLines) +	{ +		DebugAssert( m_IB ); +		if (!SetTopologyD3D11(kPrimitiveLines,device,ctx)) +			return; +		D3D11_CALL (ctx->IASetIndexBuffer (m_IB, DXGI_FORMAT_R16_UINT, 0)); +		D3D11_CALL (ctx->DrawIndexed (m_LastChunkIndices, m_LastChunkStartIndex, m_LastChunkStartVertex)); +		primCount = m_LastChunkIndices/2; +	} +	else if (m_LastRenderMode == kDrawIndexedPoints) +	{ +		DebugAssert (m_IB); +		D3D11_CALL (ctx->IASetIndexBuffer (m_IB, DXGI_FORMAT_R16_UINT, 0)); +		if (!SetTopologyD3D11 (kPrimitivePoints, device, ctx)) +			return; +		D3D11_CALL (ctx->DrawIndexed (m_LastChunkIndices, m_LastChunkStartIndex, m_LastChunkStartVertex)); +		primCount = m_LastChunkIndices; +	} +	else +	{ +		DebugAssert (m_IB); +		D3D11_CALL (ctx->IASetIndexBuffer (m_IB, DXGI_FORMAT_R16_UINT, 0)); +		if (!SetTopologyD3D11 (kPrimitiveTriangles, device, ctx)) +			return; +		D3D11_CALL (ctx->DrawIndexed (m_LastChunkIndices, m_LastChunkStartIndex, m_LastChunkStartVertex)); +		primCount = m_LastChunkIndices/3; +	} +	stats.AddDrawCall (primCount, m_LastChunkVertices); +	DX11_MARK_DRAWING(primCount, m_LastChunkVertices); +} + + +#if UNITY_EDITOR +void DynamicD3D11VBO::DrawChunkUserPrimitives (GfxPrimitiveType type) +{ +	// just return if nothing to render +	if( !m_LastChunkShaderChannelMask ) +		return; + +	HRESULT hr; + +	AssertIf( !m_LastChunkShaderChannelMask || !m_LastChunkStride ); +	AssertIf( m_LendedChunk ); + +	ChannelAssigns channels; +	for( int i = 0; i < kShaderChannelCount; ++i ) +	{ +		if (!(m_LastChunkShaderChannelMask & (1<<i))) +			continue; +		VertexComponent destComponent = kSuitableVertexComponentForChannel[i]; +		channels.Bind ((ShaderChannel)i, destComponent); +	} + +	GfxDevice& device = GetRealGfxDevice(); +	ID3D11DeviceContext* ctx = GetD3D11Context(); + +	// setup VBO +	DebugAssert (m_VB); +	UINT strides = m_LastChunkStride; +	UINT offsets = 0; +	D3D11_CALL (ctx->IASetVertexBuffers(0, 1, &m_VB, &strides, &offsets)); + +	UpdateChannelBindingsD3D11(channels); +	device.BeforeDrawCall (false); + +	ID3D11InputLayout* inputLayout = GetD3D11VertexDeclaration (m_LastChunkShaderChannelMask); +	SetInputLayoutD3D11 (ctx, inputLayout); + +	// draw +	GfxDeviceStats& stats = device.GetFrameStats(); +	int primCount = 0; +	switch (type) +	{ +	case kPrimitiveTriangles: +		if (!SetTopologyD3D11(kPrimitiveTriangles,device,ctx)) +			return; +		D3D11_CALL (ctx->Draw (m_LastChunkVertices, m_LastChunkStartVertex)); +		primCount = m_LastChunkVertices/3; +		break; +	case kPrimitiveQuads: +		if (!SetTopologyD3D11(kPrimitiveTriangles,device,ctx)) +			return; +		// initialize quads index buffer if needed +		if (!m_QuadsIB) +			InitializeQuadsIB(); +		// if quads index buffer has valid data, draw with it +		if (m_QuadsIB) +		{ +			D3D11_CALL (ctx->IASetIndexBuffer (m_QuadsIB, DXGI_FORMAT_R16_UINT, 0)); +			D3D11_CALL (ctx->DrawIndexed (m_LastChunkVertices/4*6, 0, m_LastChunkStartVertex)); +			primCount = m_LastChunkVertices/2; +		} +		break; +	case kPrimitiveLines: +		if (!SetTopologyD3D11(kPrimitiveLines,device,ctx)) +			return; +		D3D11_CALL (ctx->Draw (m_LastChunkVertices, m_LastChunkStartVertex)); +		primCount = m_LastChunkVertices/2; +		break; +	case kPrimitiveLineStrip: +		if (!SetTopologyD3D11(kPrimitiveLineStrip,device,ctx)) +			return; +		D3D11_CALL (ctx->Draw (m_LastChunkVertices, m_LastChunkStartVertex)); +		primCount = m_LastChunkVertices-1; +		break; +	default: +		ErrorString("Primitive type not supported"); +		return; +	} +	stats.AddDrawCall (primCount, m_LastChunkVertices); +} +#endif // UNITY_EDITOR + + +bool DynamicD3D11VBO::GetChunk( UInt32 shaderChannelMask, UInt32 maxVertices, UInt32 maxIndices, RenderMode renderMode, void** outVB, void** outIB ) +{ +	Assert( !m_LendedChunk ); +	Assert( maxVertices < 65536 && maxIndices < 65536*3 ); +	DebugAssertMsg(outVB != NULL && maxVertices > 0, "DynamicD3D11VBO::GetChunk - outVB: 0x%08x maxVertices: %d", outVB, maxVertices); +	DebugAssertMsg( +		(renderMode == kDrawIndexedQuads			&& (outIB != NULL && maxIndices > 0)) || +		(renderMode == kDrawIndexedPoints			&& (outIB != NULL && maxIndices > 0)) || +		(renderMode == kDrawIndexedLines			&& (outIB != NULL && maxIndices > 0)) || +		(renderMode == kDrawIndexedTriangles		&& (outIB != NULL && maxIndices > 0)) || +		(renderMode == kDrawIndexedTriangleStrip	&& (outIB != NULL && maxIndices > 0)) || +		(renderMode == kDrawTriangleStrip			&& (outIB == NULL && maxIndices == 0)) || +		(renderMode == kDrawQuads					&& (outIB == NULL && maxIndices == 0)), +		"DynamicD3D11VBO::GetChunk - renderMode: %d outIB: 0x%08x maxIndices: %d", renderMode, outIB, maxIndices); + +	HRESULT hr; +	bool success = true; + +	m_LendedChunk = true; +	m_LastChunkShaderChannelMask = shaderChannelMask; +	m_LastRenderMode = renderMode; + +	if( maxVertices == 0 ) +		maxVertices = 8; + +	m_LastChunkStride = 0; +	for( int i = 0; i < kShaderChannelCount; ++i ) { +		if( shaderChannelMask & (1<<i) ) +			m_LastChunkStride += VBO::GetDefaultChannelByteSize(i); +	} +	ID3D11Device* dev = GetD3D11Device(); +	ID3D11DeviceContext* ctx = GetD3D11Context(); + +	// -------- vertex buffer + +	DebugAssertIf( !outVB ); +	UInt32 vbCapacity = maxVertices * m_LastChunkStride; +	// check if requested chunk is larger than current buffer +	if( vbCapacity > m_VBSize ) { +		m_VBSize = vbCapacity * 2; // allocate more up front +		if( m_VB ) +		{ +			REGISTER_EXTERNAL_GFX_DEALLOCATION(m_VB); +			m_VB->Release(); +		} +		m_VB = NULL; +	} +	// allocate buffer if don't have it yet +	if( !m_VB ) +	{ +		D3D11_BUFFER_DESC desc; +		desc.ByteWidth = m_VBSize; +		desc.Usage = D3D11_USAGE_DYNAMIC; +		desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; +		desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; +		desc.MiscFlags = 0; +		desc.StructureByteStride = 0; +		hr = dev->CreateBuffer (&desc, NULL, &m_VB); +		REGISTER_EXTERNAL_GFX_ALLOCATION_REF(m_VB,m_VBSize,this); +		if (FAILED(hr)) +		{ +			printf_console ("d3d11: failed to create dynamic vertex buffer of size %d [%x]\n", m_VBSize, hr); +			success = false; +			*outVB = NULL; +		} +		SetDebugNameD3D11 (m_VB, Format("VertexBufferDynamic-%d", m_VBSize)); +	} + +	// map, making sure the offset we lock is multiple of vertex stride +	if (m_VB) +	{ +		m_VBUsedBytes = ((m_VBUsedBytes + (m_LastChunkStride-1)) / m_LastChunkStride) * m_LastChunkStride; +		if (m_VBUsedBytes + vbCapacity > m_VBSize) +		{ +			D3D11_MAPPED_SUBRESOURCE mapped; +			hr = ctx->Map (m_VB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped); +			if (FAILED(hr)) +			{ +				printf_console ("d3d11: failed to lock dynamic vertex buffer with discard [%x]\n", hr); +				*outVB = NULL; +				success = false; +			} +			*outVB = mapped.pData; +			m_VBUsedBytes = 0; +		} else { +			D3D11_MAPPED_SUBRESOURCE mapped; +			hr = ctx->Map (m_VB, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped); +			if (FAILED(hr)) +			{ +				printf_console ("d3d11: failed to lock vertex index buffer, offset %i size %i [%x]\n", m_VBUsedBytes, vbCapacity, hr); +				*outVB = NULL; +				success = false; +			} +			*outVB = ((UInt8*)mapped.pData) + m_VBUsedBytes; +		} +		m_LastChunkStartVertex = m_VBUsedBytes / m_LastChunkStride; +		DebugAssertIf( m_LastChunkStartVertex * m_LastChunkStride != m_VBUsedBytes ); +	} + +	// -------- index buffer + +	const bool indexed = (renderMode != kDrawQuads) && (renderMode != kDrawTriangleStrip); +	if( success && maxIndices && indexed ) +	{ +		UInt32 ibCapacity = maxIndices * kVBOIndexSize; +		// check if requested chunk is larger than current buffer +		if( ibCapacity > m_IBSize ) { +			m_IBSize = ibCapacity * 2; // allocate more up front +			if( m_IB ) +			{ +				REGISTER_EXTERNAL_GFX_DEALLOCATION(m_IB); +				m_IB->Release(); +			} +			m_IB = NULL; +		} +		// allocate buffer if don't have it yet +		if( !m_IB ) +		{ +			D3D11_BUFFER_DESC desc; +			desc.ByteWidth = m_IBSize; +			desc.Usage = D3D11_USAGE_DYNAMIC; +			desc.BindFlags = D3D11_BIND_INDEX_BUFFER; +			desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; +			desc.MiscFlags = 0; +			desc.StructureByteStride = 0; +			hr = dev->CreateBuffer (&desc, NULL, &m_IB); +			REGISTER_EXTERNAL_GFX_ALLOCATION_REF(m_IB,m_IBSize,this); +			if (FAILED(hr)) +			{ +				printf_console ("d3d11: failed to create dynamic index buffer of size %d [%x]\n", m_IBSize, hr); +				if (m_VB) +					ctx->Unmap (m_VB, 0); +			} +			SetDebugNameD3D11 (m_IB, Format("IndexBufferDynamic-%d", m_IBSize)); +		} +		// lock it if we have IB created successfully +		if( m_IB ) +		{ +			if( m_IBUsedBytes + ibCapacity > m_IBSize ) +			{ +				D3D11_MAPPED_SUBRESOURCE mapped; +				hr = ctx->Map (m_IB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped); +				if (FAILED(hr)) +				{ +					printf_console ("d3d11: failed to lock dynamic index buffer with discard [%x]\n", hr); +					*outIB = NULL; +					success = false; +					if (m_VB) +						ctx->Unmap (m_VB, 0); +				} +				*outIB = mapped.pData; +				m_IBUsedBytes = 0; +			} else { +				D3D11_MAPPED_SUBRESOURCE mapped; +				hr = ctx->Map (m_IB, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped); +				if (FAILED(hr)) +				{ +					printf_console ("d3d11: failed to lock dynamic index buffer, offset %i size %i [%x]\n", m_IBUsedBytes, ibCapacity, hr); +					*outIB = NULL; +					success = false; +					if (m_VB) +						ctx->Unmap (m_VB, 0); +				} +				*outIB = ((UInt8*)mapped.pData) + m_IBUsedBytes; +			} +			m_LastChunkStartIndex = m_IBUsedBytes / 2; +		} +		else +		{ +			*outIB = NULL; +			success = false; +		} +	} + +	if( !success ) +		m_LendedChunk = false; + +	return success; +} + +void DynamicD3D11VBO::ReleaseChunk( UInt32 actualVertices, UInt32 actualIndices ) +{ +	Assert( m_LendedChunk ); +	Assert( m_LastRenderMode == kDrawIndexedTriangleStrip || m_LastRenderMode == kDrawIndexedQuads || m_LastRenderMode == kDrawIndexedPoints || m_LastRenderMode == kDrawIndexedLines || actualIndices % 3 == 0 ); +	m_LendedChunk = false; + +	const bool indexed = (m_LastRenderMode != kDrawQuads) && (m_LastRenderMode != kDrawTriangleStrip); +	 +	m_LastChunkVertices = actualVertices; +	m_LastChunkIndices = actualIndices; + +	// unlock buffers +	ID3D11DeviceContext* ctx = GetD3D11Context(); +	ctx->Unmap (m_VB, 0); +	if (indexed) +		ctx->Unmap (m_IB, 0); + +	if( !actualVertices || (indexed && !actualIndices) ) { +		m_LastChunkShaderChannelMask = 0; +		return; +	} + +	UInt32 actualVBSize = actualVertices * m_LastChunkStride; +	m_VBUsedBytes += actualVBSize; +	UInt32 actualIBSize = actualIndices * kVBOIndexSize; +	m_IBUsedBytes += actualIBSize; +} + + | 
