bool FD3D11DynamicRHI::RHIGetRenderQueryResult(FRenderQueryRHIParamRef QueryRHI,uint64& OutResult,bool bWait) { DYNAMIC_CAST_D3D11RESOURCE(OcclusionQuery,Query); bool bSuccess = true; if(!Query->bResultIsCached) { bSuccess = GetQueryData(Query->Resource,&Query->Result,sizeof(Query->Result),bWait, Query->QueryType); Query->bResultIsCached = bSuccess; } if(Query->QueryType == RQT_AbsoluteTime) { // GetTimingFrequency is the number of ticks per second uint64 Div = FGPUTiming::GetTimingFrequency() / (1000 * 1000); // convert from GPU specific timestamp to micro sec (1 / 1 000 000 s) which seems a reasonable resolution OutResult = Query->Result / Div; } else { OutResult = Query->Result; } return bSuccess; }
FUnorderedAccessViewRHIRef FD3D11DynamicRHI::RHICreateUnorderedAccessView(FVertexBufferRHIParamRef VertexBufferRHI, uint8 Format) { DYNAMIC_CAST_D3D11RESOURCE(VertexBuffer,VertexBuffer); D3D11_BUFFER_DESC BufferDesc; VertexBuffer->Resource->GetDesc(&BufferDesc); const bool bByteAccessBuffer = (BufferDesc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) != 0; D3D11_UNORDERED_ACCESS_VIEW_DESC UAVDesc; UAVDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; UAVDesc.Format = FindUnorderedAccessDXGIFormat((DXGI_FORMAT)GPixelFormats[Format].PlatformFormat); UAVDesc.Buffer.FirstElement = 0; UAVDesc.Buffer.NumElements = BufferDesc.ByteWidth / GPixelFormats[Format].BlockBytes; UAVDesc.Buffer.Flags = 0; if (bByteAccessBuffer) { UAVDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_RAW; UAVDesc.Format = DXGI_FORMAT_R32_TYPELESS; } TRefCountPtr<ID3D11UnorderedAccessView> UnorderedAccessView; VERIFYD3D11RESULT(Direct3DDevice->CreateUnorderedAccessView(VertexBuffer->Resource,&UAVDesc,(ID3D11UnorderedAccessView**)UnorderedAccessView.GetInitReference())); return new FD3D11UnorderedAccessView(UnorderedAccessView,VertexBuffer); }
void FD3D11DynamicRHI::RHIResizeViewport(FViewportRHIParamRef ViewportRHI,uint32 SizeX,uint32 SizeY,bool bIsFullscreen) { DYNAMIC_CAST_D3D11RESOURCE(Viewport,Viewport); check( IsInGameThread() ); Viewport->Resize(SizeX,SizeY,bIsFullscreen); }
FShaderResourceViewRHIRef FD3D11DynamicRHI::RHICreateShaderResourceView(FStructuredBufferRHIParamRef StructuredBufferRHI) { DYNAMIC_CAST_D3D11RESOURCE(StructuredBuffer,StructuredBuffer); D3D11_BUFFER_DESC BufferDesc; StructuredBuffer->Resource->GetDesc(&BufferDesc); const bool bByteAccessBuffer = (BufferDesc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) != 0; // Create a Shader Resource View D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; if ( bByteAccessBuffer ) { SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; SRVDesc.BufferEx.NumElements = BufferDesc.ByteWidth / 4; SRVDesc.BufferEx.FirstElement = 0; SRVDesc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW; SRVDesc.Format = DXGI_FORMAT_R32_TYPELESS; } else { SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; SRVDesc.Buffer.FirstElement = 0; SRVDesc.Buffer.NumElements = BufferDesc.ByteWidth / BufferDesc.StructureByteStride; SRVDesc.Format = DXGI_FORMAT_UNKNOWN; } TRefCountPtr<ID3D11ShaderResourceView> ShaderResourceView; VERIFYD3D11RESULT(Direct3DDevice->CreateShaderResourceView(StructuredBuffer->Resource, &SRVDesc, (ID3D11ShaderResourceView**)ShaderResourceView.GetInitReference())); return new FD3D11ShaderResourceView(ShaderResourceView,StructuredBuffer); }
void FD3D11DynamicRHI::RHIClearUAV(FUnorderedAccessViewRHIParamRef UnorderedAccessViewRHI, const uint32* Values) { DYNAMIC_CAST_D3D11RESOURCE(UnorderedAccessView,UnorderedAccessView); Direct3DDeviceIMContext->ClearUnorderedAccessViewUint(UnorderedAccessView->View, Values); GPUProfilingData.RegisterGPUWork(1); }
void FD3D11DynamicRHI::RHICopyVertexBuffer(FVertexBufferRHIParamRef SourceBufferRHI,FVertexBufferRHIParamRef DestBufferRHI) { DYNAMIC_CAST_D3D11RESOURCE(VertexBuffer,SourceBuffer); DYNAMIC_CAST_D3D11RESOURCE(VertexBuffer,DestBuffer); D3D11_BUFFER_DESC SourceBufferDesc; SourceBuffer->Resource->GetDesc(&SourceBufferDesc); D3D11_BUFFER_DESC DestBufferDesc; DestBuffer->Resource->GetDesc(&DestBufferDesc); check(SourceBufferDesc.ByteWidth == DestBufferDesc.ByteWidth); Direct3DDeviceIMContext->CopyResource(DestBuffer->Resource,SourceBuffer->Resource); GPUProfilingData.RegisterGPUWork(1); }
void FD3D11DynamicRHI::RHIEndRenderQuery(FRenderQueryRHIParamRef QueryRHI) { DYNAMIC_CAST_D3D11RESOURCE(OcclusionQuery,Query); #if PLATFORM_SUPPORTS_RHI_THREAD Query->bResultIsCached = false; // for occlusion queries, this is redundant with the one in begin #endif Direct3DDeviceIMContext->End(Query->Resource); //@todo - d3d debug spews warnings about OQ's that are being issued but not polled, need to investigate }
FUnorderedAccessViewRHIRef FD3D11DynamicRHI::RHICreateUnorderedAccessView(FStructuredBufferRHIParamRef StructuredBufferRHI, bool bUseUAVCounter, bool bAppendBuffer) { DYNAMIC_CAST_D3D11RESOURCE(StructuredBuffer,StructuredBuffer); D3D11_BUFFER_DESC BufferDesc; StructuredBuffer->Resource->GetDesc(&BufferDesc); const bool bByteAccessBuffer = (BufferDesc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) != 0; D3D11_UNORDERED_ACCESS_VIEW_DESC UAVDesc; UAVDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; UAVDesc.Format = DXGI_FORMAT_UNKNOWN; if (BufferDesc.MiscFlags & D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS) { UAVDesc.Format = DXGI_FORMAT_R32_UINT; } else if (bByteAccessBuffer) { UAVDesc.Format = DXGI_FORMAT_R32_TYPELESS; } UAVDesc.Buffer.FirstElement = 0; // For byte access buffers and indirect draw argument buffers, GetDesc returns a StructureByteStride of 0 even though we created it with 4 const uint32 EffectiveStride = BufferDesc.StructureByteStride == 0 ? 4 : BufferDesc.StructureByteStride; UAVDesc.Buffer.NumElements = BufferDesc.ByteWidth / EffectiveStride; UAVDesc.Buffer.Flags = 0; if (bUseUAVCounter) { UAVDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_COUNTER; } if (bAppendBuffer) { UAVDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_APPEND; } if (bByteAccessBuffer) { UAVDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_RAW; } TRefCountPtr<ID3D11UnorderedAccessView> UnorderedAccessView; VERIFYD3D11RESULT(Direct3DDevice->CreateUnorderedAccessView(StructuredBuffer->Resource,&UAVDesc,(ID3D11UnorderedAccessView**)UnorderedAccessView.GetInitReference())); return new FD3D11UnorderedAccessView(UnorderedAccessView,StructuredBuffer); }
// Occlusion/Timer queries. void FD3D11DynamicRHI::RHIBeginRenderQuery(FRenderQueryRHIParamRef QueryRHI) { DYNAMIC_CAST_D3D11RESOURCE(OcclusionQuery,Query); if(Query->QueryType == RQT_Occlusion) { #if PLATFORM_SUPPORTS_RHI_THREAD Query->bResultIsCached = false; #endif Direct3DDeviceIMContext->Begin(Query->Resource); } else { // not supported/needed for RQT_AbsoluteTime check(0); } }
void FD3D11DynamicRHI::RHIUnlockVertexBuffer(FVertexBufferRHIParamRef VertexBufferRHI) { DYNAMIC_CAST_D3D11RESOURCE(VertexBuffer,VertexBuffer); // Determine whether the vertex buffer is dynamic or not. D3D11_BUFFER_DESC Desc; VertexBuffer->Resource->GetDesc(&Desc); const bool bIsDynamic = (Desc.Usage == D3D11_USAGE_DYNAMIC); // Find the outstanding lock for this VB. FD3D11LockedKey LockedKey(VertexBuffer->Resource); FD3D11LockedData* LockedData = OutstandingLocks.Find(LockedKey); check(LockedData); if(bIsDynamic) { // If the VB is dynamic, its memory was mapped directly; unmap it. Direct3DDeviceIMContext->Unmap(VertexBuffer->Resource,0); } else { // If the static VB lock involved a staging resource, it was locked for reading. if(LockedData->StagingResource) { // Unmap the staging buffer's memory. ID3D11Buffer* StagingBuffer = (ID3D11Buffer*)LockedData->StagingResource.GetReference(); Direct3DDeviceIMContext->Unmap(StagingBuffer,0); } else { // Copy the contents of the temporary memory buffer allocated for writing into the VB. Direct3DDeviceIMContext->UpdateSubresource(VertexBuffer->Resource,LockedKey.Subresource,NULL,LockedData->GetData(),LockedData->Pitch,0); // Free the temporary memory buffer. LockedData->FreeData(); } } // Remove the FD3D11LockedData from the lock map. // If the lock involved a staging resource, this releases it. OutstandingLocks.Remove(LockedKey); }
void FD3D11DynamicRHI::RHIBeginDrawingViewport(FViewportRHIParamRef ViewportRHI, FTextureRHIParamRef RenderTarget) { DYNAMIC_CAST_D3D11RESOURCE(Viewport,Viewport); SCOPE_CYCLE_COUNTER(STAT_D3D11PresentTime); check(!DrawingViewport); DrawingViewport = Viewport; // Set the render target and viewport. if( RenderTarget == NULL ) { RenderTarget = Viewport->GetBackBuffer(); } FRHIRenderTargetView View(RenderTarget); RHISetRenderTargets(1,&View,FTextureRHIRef(),0,NULL); // Set an initially disabled scissor rect. RHISetScissorRect(false,0,0,0,0); }
FD3D11BoundShaderState::FD3D11BoundShaderState( FVertexDeclarationRHIParamRef InVertexDeclarationRHI, FVertexShaderRHIParamRef InVertexShaderRHI, FPixelShaderRHIParamRef InPixelShaderRHI, FHullShaderRHIParamRef InHullShaderRHI, FDomainShaderRHIParamRef InDomainShaderRHI, FGeometryShaderRHIParamRef InGeometryShaderRHI, ID3D11Device* Direct3DDevice ): CacheLink(InVertexDeclarationRHI,InVertexShaderRHI,InPixelShaderRHI,InHullShaderRHI,InDomainShaderRHI,InGeometryShaderRHI,this) { INC_DWORD_STAT(STAT_D3D11NumBoundShaderState); DYNAMIC_CAST_D3D11RESOURCE(VertexDeclaration,InVertexDeclaration); DYNAMIC_CAST_D3D11RESOURCE(VertexShader,InVertexShader); DYNAMIC_CAST_D3D11RESOURCE(PixelShader,InPixelShader); DYNAMIC_CAST_D3D11RESOURCE(HullShader,InHullShader); DYNAMIC_CAST_D3D11RESOURCE(DomainShader,InDomainShader); DYNAMIC_CAST_D3D11RESOURCE(GeometryShader,InGeometryShader); // Create an input layout for this combination of vertex declaration and vertex shader. D3D11_INPUT_ELEMENT_DESC NullInputElement; FMemory::Memzero(&NullInputElement,sizeof(D3D11_INPUT_ELEMENT_DESC)); VERIFYD3D11RESULT(Direct3DDevice->CreateInputLayout( InVertexDeclaration ? InVertexDeclaration->VertexElements.GetData() : &NullInputElement, InVertexDeclaration ? InVertexDeclaration->VertexElements.Num() : 0, &InVertexShader->Code[ InVertexShader->Offset ], // TEMP ugly InVertexShader->Code.Num() - 1 - InVertexShader->Offset, InputLayout.GetInitReference() )); VertexShader = InVertexShader->Resource; PixelShader = InPixelShader ? InPixelShader->Resource : NULL; HullShader = InHullShader ? InHullShader->Resource : NULL; DomainShader = InDomainShader ? InDomainShader->Resource : NULL; GeometryShader = InGeometryShader ? InGeometryShader->Resource : NULL; FMemory::Memzero(&bShaderNeedsGlobalConstantBuffer,sizeof(bShaderNeedsGlobalConstantBuffer)); bShaderNeedsGlobalConstantBuffer[SF_Vertex] = InVertexShader->bShaderNeedsGlobalConstantBuffer; bShaderNeedsGlobalConstantBuffer[SF_Hull] = InHullShader ? InHullShader->bShaderNeedsGlobalConstantBuffer : false; bShaderNeedsGlobalConstantBuffer[SF_Domain] = InDomainShader ? InDomainShader->bShaderNeedsGlobalConstantBuffer : false; bShaderNeedsGlobalConstantBuffer[SF_Pixel] = InPixelShader ? InPixelShader->bShaderNeedsGlobalConstantBuffer : false; bShaderNeedsGlobalConstantBuffer[SF_Geometry] = InGeometryShader ? InGeometryShader->bShaderNeedsGlobalConstantBuffer : false; static_assert(ARRAY_COUNT(bShaderNeedsGlobalConstantBuffer) == SF_NumFrequencies, "EShaderFrequency size should match with array count of bShaderNeedsGlobalConstantBuffer."); }
FD3D11BoundShaderState::FD3D11BoundShaderState( FVertexDeclarationRHIParamRef InVertexDeclarationRHI, FVertexShaderRHIParamRef InVertexShaderRHI, FPixelShaderRHIParamRef InPixelShaderRHI, FHullShaderRHIParamRef InHullShaderRHI, FDomainShaderRHIParamRef InDomainShaderRHI, FGeometryShaderRHIParamRef InGeometryShaderRHI, ID3D11Device* Direct3DDevice ): CacheLink(InVertexDeclarationRHI,InVertexShaderRHI,InPixelShaderRHI,InHullShaderRHI,InDomainShaderRHI,InGeometryShaderRHI,this) { DYNAMIC_CAST_D3D11RESOURCE(VertexDeclaration,InVertexDeclaration); DYNAMIC_CAST_D3D11RESOURCE(VertexShader,InVertexShader); DYNAMIC_CAST_D3D11RESOURCE(PixelShader,InPixelShader); DYNAMIC_CAST_D3D11RESOURCE(HullShader,InHullShader); DYNAMIC_CAST_D3D11RESOURCE(DomainShader,InDomainShader); DYNAMIC_CAST_D3D11RESOURCE(GeometryShader,InGeometryShader); // Create an input layout for this combination of vertex declaration and vertex shader. D3D11_INPUT_ELEMENT_DESC NullInputElement; FMemory::Memzero(&NullInputElement,sizeof(D3D11_INPUT_ELEMENT_DESC)); VERIFYD3D11RESULT(Direct3DDevice->CreateInputLayout( InVertexDeclaration ? InVertexDeclaration->VertexElements.GetTypedData() : &NullInputElement, InVertexDeclaration ? InVertexDeclaration->VertexElements.Num() : 0, InVertexShader->Code.GetTypedData(), InVertexShader->Code.Num() - 1, InputLayout.GetInitReference() )); VertexShader = InVertexShader->Resource; PixelShader = InPixelShader ? InPixelShader->Resource : NULL; HullShader = InHullShader ? InHullShader->Resource : NULL; DomainShader = InDomainShader ? InDomainShader->Resource : NULL; GeometryShader = InGeometryShader ? InGeometryShader->Resource : NULL; FMemory::Memzero(&bShaderNeedsGlobalConstantBuffer,sizeof(bShaderNeedsGlobalConstantBuffer)); bShaderNeedsGlobalConstantBuffer[SF_Vertex] = InVertexShader->bShaderNeedsGlobalConstantBuffer; bShaderNeedsGlobalConstantBuffer[SF_Hull] = InHullShader ? InHullShader->bShaderNeedsGlobalConstantBuffer : false; bShaderNeedsGlobalConstantBuffer[SF_Domain] = InDomainShader ? InDomainShader->bShaderNeedsGlobalConstantBuffer : false; bShaderNeedsGlobalConstantBuffer[SF_Pixel] = InPixelShader ? InPixelShader->bShaderNeedsGlobalConstantBuffer : false; bShaderNeedsGlobalConstantBuffer[SF_Geometry] = InGeometryShader ? InGeometryShader->bShaderNeedsGlobalConstantBuffer : false; checkAtCompileTime(ARRAY_COUNT(bShaderNeedsGlobalConstantBuffer) == SF_NumFrequencies, NumFrequenciesMismatch); }
FShaderResourceViewRHIRef FD3D11DynamicRHI::RHICreateShaderResourceView(FVertexBufferRHIParamRef VertexBufferRHI, uint32 Stride, uint8 Format) { DYNAMIC_CAST_D3D11RESOURCE(VertexBuffer,VertexBuffer); check(VertexBuffer); check(VertexBuffer->Resource); D3D11_BUFFER_DESC BufferDesc; VertexBuffer->Resource->GetDesc(&BufferDesc); // Create a Shader Resource View D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; FMemory::Memzero(SRVDesc); SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; SRVDesc.Buffer.FirstElement = 0; SRVDesc.Format = FindShaderResourceDXGIFormat((DXGI_FORMAT)GPixelFormats[Format].PlatformFormat,false); SRVDesc.Buffer.NumElements = BufferDesc.ByteWidth / Stride; TRefCountPtr<ID3D11ShaderResourceView> ShaderResourceView; HRESULT hr = Direct3DDevice->CreateShaderResourceView(VertexBuffer->Resource, &SRVDesc, (ID3D11ShaderResourceView**)ShaderResourceView.GetInitReference()); if (FAILED(hr)) { if (hr == E_OUTOFMEMORY) { // There appears to be a driver bug that causes SRV creation to fail with an OOM error and then succeed on the next call. hr = Direct3DDevice->CreateShaderResourceView(VertexBuffer->Resource, &SRVDesc, (ID3D11ShaderResourceView**)ShaderResourceView.GetInitReference()); } if (FAILED(hr)) { UE_LOG(LogD3D11RHI,Error,TEXT("Failed to create shader resource view for vertex buffer: ByteWidth=%d NumElements=%d"),BufferDesc.ByteWidth,BufferDesc.ByteWidth / Stride); VerifyD3D11Result(hr,"Direct3DDevice->CreateShaderResourceView",__FILE__,__LINE__,Direct3DDevice); } } return new FD3D11ShaderResourceView(ShaderResourceView,VertexBuffer); }
void FD3D11DynamicRHI::RHIResetRenderQuery(FRenderQueryRHIParamRef QueryRHI) { DYNAMIC_CAST_D3D11RESOURCE(OcclusionQuery,Query); Query->bResultIsCached = false; }
void FD3D11DynamicRHI::RHIEndDrawingViewport(FViewportRHIParamRef ViewportRHI,bool bPresent,bool bLockToVsync) { DYNAMIC_CAST_D3D11RESOURCE(Viewport,Viewport); SCOPE_CYCLE_COUNTER(STAT_D3D11PresentTime); check(DrawingViewport.GetReference() == Viewport); DrawingViewport = NULL; // Clear references the device might have to resources. CurrentDepthTexture = NULL; CurrentDepthStencilTarget = NULL; CurrentDSVAccessType = DSAT_Writable; CurrentRenderTargets[0] = NULL; for(uint32 RenderTargetIndex = 1;RenderTargetIndex < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;++RenderTargetIndex) { CurrentRenderTargets[RenderTargetIndex] = NULL; } ClearAllShaderResources(); CommitRenderTargetsAndUAVs(); StateCache.SetVertexShader(nullptr); for(uint32 StreamIndex = 0;StreamIndex < 16;StreamIndex++) { StateCache.SetStreamSource(nullptr, StreamIndex, 0, 0); } StateCache.SetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0); StateCache.SetPixelShader(nullptr); StateCache.SetHullShader(nullptr); StateCache.SetDomainShader(nullptr); StateCache.SetGeometryShader(nullptr); // Compute Shader is set to NULL after each Dispatch call, so no need to clear it here bool bNativelyPresented = Viewport->Present(bLockToVsync); // Don't wait on the GPU when using SLI, let the driver determine how many frames behind the GPU should be allowed to get if (GNumActiveGPUsForRendering == 1) { if (bNativelyPresented) { static const auto CFinishFrameVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.FinishCurrentFrame")); if (!CFinishFrameVar->GetValueOnRenderThread()) { // Wait for the GPU to finish rendering the previous frame before finishing this frame. Viewport->WaitForFrameEventCompletion(); Viewport->IssueFrameEvent(); } else { // Finish current frame immediately to reduce latency Viewport->IssueFrameEvent(); Viewport->WaitForFrameEventCompletion(); } } // If the input latency timer has been triggered, block until the GPU is completely // finished displaying this frame and calculate the delta time. if ( GInputLatencyTimer.RenderThreadTrigger ) { Viewport->WaitForFrameEventCompletion(); uint32 EndTime = FPlatformTime::Cycles(); GInputLatencyTimer.DeltaTime = EndTime - GInputLatencyTimer.StartTime; GInputLatencyTimer.RenderThreadTrigger = false; } } }
FTexture2DRHIRef FD3D11DynamicRHI::RHIGetViewportBackBuffer(FViewportRHIParamRef ViewportRHI) { DYNAMIC_CAST_D3D11RESOURCE(Viewport,Viewport); return Viewport->GetBackBuffer(); }
void* FD3D11DynamicRHI::RHILockVertexBuffer(FVertexBufferRHIParamRef VertexBufferRHI,uint32 Offset,uint32 Size,EResourceLockMode LockMode) { check(Size > 0); DYNAMIC_CAST_D3D11RESOURCE(VertexBuffer,VertexBuffer); // If this resource is bound to the device, unbind it ConditionalClearShaderResource(VertexBuffer); // Determine whether the vertex buffer is dynamic or not. D3D11_BUFFER_DESC Desc; VertexBuffer->Resource->GetDesc(&Desc); const bool bIsDynamic = (Desc.Usage == D3D11_USAGE_DYNAMIC); FD3D11LockedKey LockedKey(VertexBuffer->Resource); FD3D11LockedData LockedData; if(bIsDynamic) { check(LockMode == RLM_WriteOnly); // If the buffer is dynamic, map its memory for writing. D3D11_MAPPED_SUBRESOURCE MappedSubresource; VERIFYD3D11RESULT(Direct3DDeviceIMContext->Map(VertexBuffer->Resource,0,D3D11_MAP_WRITE_DISCARD,0,&MappedSubresource)); LockedData.SetData(MappedSubresource.pData); LockedData.Pitch = MappedSubresource.RowPitch; } else { if(LockMode == RLM_ReadOnly) { // If the static buffer is being locked for reading, create a staging buffer. D3D11_BUFFER_DESC StagingBufferDesc; ZeroMemory( &StagingBufferDesc, sizeof( D3D11_BUFFER_DESC ) ); StagingBufferDesc.ByteWidth = Size; StagingBufferDesc.Usage = D3D11_USAGE_STAGING; StagingBufferDesc.BindFlags = 0; StagingBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; StagingBufferDesc.MiscFlags = 0; TRefCountPtr<ID3D11Buffer> StagingVertexBuffer; VERIFYD3D11RESULT(Direct3DDevice->CreateBuffer(&StagingBufferDesc,NULL,StagingVertexBuffer.GetInitReference())); LockedData.StagingResource = StagingVertexBuffer; // Copy the contents of the vertex buffer to the staging buffer. D3D11_BOX SourceBox; SourceBox.left = Offset; SourceBox.right = Size; SourceBox.top = SourceBox.front = 0; SourceBox.bottom = SourceBox.back = 1; Direct3DDeviceIMContext->CopySubresourceRegion(StagingVertexBuffer,0,0,0,0,VertexBuffer->Resource,0,&SourceBox); // Map the staging buffer's memory for reading. D3D11_MAPPED_SUBRESOURCE MappedSubresource; VERIFYD3D11RESULT(Direct3DDeviceIMContext->Map(StagingVertexBuffer,0,D3D11_MAP_READ,0,&MappedSubresource)); LockedData.SetData(MappedSubresource.pData); LockedData.Pitch = MappedSubresource.RowPitch; } else { // If the static buffer is being locked for writing, allocate memory for the contents to be written to. LockedData.AllocData(Desc.ByteWidth); LockedData.Pitch = Desc.ByteWidth; } } // Add the lock to the lock map. OutstandingLocks.Add(LockedKey,LockedData); // Return the offset pointer return (void*)((uint8*)LockedData.GetData() + Offset); }