FD3D12ResourceLocation* FD3D12DynamicRHI::CreateBuffer(FRHICommandListImmediate* RHICmdList, const D3D12_RESOURCE_DESC Desc, uint32 Size, uint32 InUsage, FRHIResourceCreateInfo& CreateInfo, uint32 Alignment) { // Explicitly check that the size is nonzero before allowing CreateBuffer to opaquely fail. check(Size > 0); const bool bIsDynamic = (InUsage & BUF_AnyDynamic) ? true : false; FD3D12ResourceLocation* ResourceLocation = new FD3D12ResourceLocation(GetRHIDevice()); // If a resource array was provided for the resource, create the resource pre-populated D3D12_SUBRESOURCE_DATA InitData = { 0 }; D3D12_SUBRESOURCE_DATA* pInitData = nullptr; if (CreateInfo.ResourceArray) { check(Size == CreateInfo.ResourceArray->GetResourceDataSize()); InitData.pData = CreateInfo.ResourceArray->GetResourceData(); InitData.RowPitch = Size; InitData.SlicePitch = 0; pInitData = &InitData; } if (bIsDynamic) { void* pData = GetRHIDevice()->GetDefaultUploadHeapAllocator().AllocUploadResource(Size, Alignment, ResourceLocation); check(ResourceLocation->GetEffectiveBufferSize() == Size); if (pInitData) { // Handle initial data FMemory::Memcpy(pData, InitData.pData, Size); } } else { if (RHICmdList && pInitData) { // We only need to synchronize when creating default resource buffers (because we need a command list to initialize them) FScopedRHIThreadStaller StallRHIThread(*RHICmdList); VERIFYD3D11RESULT(GetRHIDevice()->GetDefaultBufferAllocator().AllocDefaultResource(Desc, pInitData, ResourceLocation, Alignment)); } else { VERIFYD3D11RESULT(GetRHIDevice()->GetDefaultBufferAllocator().AllocDefaultResource(Desc, pInitData, ResourceLocation, Alignment)); } check(ResourceLocation->GetEffectiveBufferSize() == Size); } if (CreateInfo.ResourceArray) { // Discard the resource array's contents. CreateInfo.ResourceArray->Discard(); } return ResourceLocation; }
FD3D11Viewport::FD3D11Viewport(FD3D11DynamicRHI* InD3DRHI,HWND InWindowHandle,uint32 InSizeX,uint32 InSizeY,bool bInIsFullscreen, EPixelFormat InPreferredPixelFormat): D3DRHI(InD3DRHI), LastFlipTime(0), LastFrameComplete(0), LastCompleteTime(0), SyncCounter(0), bSyncedLastFrame(false), WindowHandle(InWindowHandle), MaximumFrameLatency(3), SizeX(InSizeX), SizeY(InSizeY), bIsFullscreen(bInIsFullscreen), PixelFormat(InPreferredPixelFormat), bIsValid(true), FrameSyncEvent(InD3DRHI) { check(IsInGameThread()); D3DRHI->Viewports.Add(this); // Ensure that the D3D device has been created. D3DRHI->InitD3DDevice(); // Create a backbuffer/swapchain for each viewport TRefCountPtr<IDXGIDevice> DXGIDevice; VERIFYD3D11RESULT(D3DRHI->GetDevice()->QueryInterface( IID_IDXGIDevice, (void**)DXGIDevice.GetInitReference() )); // Create the swapchain. DXGI_SWAP_CHAIN_DESC SwapChainDesc; FMemory::Memzero( &SwapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC) ); SwapChainDesc.BufferDesc = SetupDXGI_MODE_DESC(); // MSAA Sample count SwapChainDesc.SampleDesc.Count = 1; SwapChainDesc.SampleDesc.Quality = 0; SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT; // 1:single buffering, 2:double buffering, 3:triple buffering SwapChainDesc.BufferCount = 1; SwapChainDesc.OutputWindow = WindowHandle; SwapChainDesc.Windowed = !bIsFullscreen; // DXGI_SWAP_EFFECT_DISCARD / DXGI_SWAP_EFFECT_SEQUENTIAL SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; VERIFYD3D11RESULT(D3DRHI->GetFactory()->CreateSwapChain(DXGIDevice,&SwapChainDesc,SwapChain.GetInitReference())); // Set the DXGI message hook to not change the window behind our back. D3DRHI->GetFactory()->MakeWindowAssociation(WindowHandle,DXGI_MWA_NO_WINDOW_CHANGES); // Create a RHI surface to represent the viewport's back buffer. BackBuffer = GetSwapChainSurface(D3DRHI, PixelFormat, SwapChain); // Tell the window to redraw when they can. // @todo: For Slate viewports, it doesn't make sense to post WM_PAINT messages (we swallow those.) ::PostMessage( WindowHandle, WM_PAINT, 0, 0 ); BeginInitResource(&FrameSyncEvent); }
/** * Creates a FD3D11Surface to represent a swap chain's back buffer. */ FD3D11Texture2D* GetSwapChainSurface(FD3D11DynamicRHI* D3DRHI,IDXGISwapChain* SwapChain) { // Grab the back buffer TRefCountPtr<ID3D11Texture2D> BackBufferResource; VERIFYD3D11RESULT_EX(SwapChain->GetBuffer(0,IID_ID3D11Texture2D,(void**)BackBufferResource.GetInitReference()), D3DRHI->GetDevice()); // create the render target view TRefCountPtr<ID3D11RenderTargetView> BackBufferRenderTargetView; D3D11_RENDER_TARGET_VIEW_DESC RTVDesc; RTVDesc.Format = DXGI_FORMAT_UNKNOWN; RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; RTVDesc.Texture2D.MipSlice = 0; VERIFYD3D11RESULT(D3DRHI->GetDevice()->CreateRenderTargetView(BackBufferResource,&RTVDesc,BackBufferRenderTargetView.GetInitReference())); D3D11_TEXTURE2D_DESC TextureDesc; BackBufferResource->GetDesc(&TextureDesc); TArray<TRefCountPtr<ID3D11RenderTargetView> > RenderTargetViews; RenderTargetViews.Add(BackBufferRenderTargetView); // create a shader resource view to allow using the backbuffer as a texture TRefCountPtr<ID3D11ShaderResourceView> BackBufferShaderResourceView; D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; SRVDesc.Format = DXGI_FORMAT_UNKNOWN; SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MostDetailedMip = 0; SRVDesc.Texture2D.MipLevels = 1; VERIFYD3D11RESULT(D3DRHI->GetDevice()->CreateShaderResourceView(BackBufferResource,&SRVDesc,BackBufferShaderResourceView.GetInitReference())); FD3D11Texture2D* NewTexture = new FD3D11Texture2D( D3DRHI, BackBufferResource, BackBufferShaderResourceView, false, 1, RenderTargetViews, NULL, TextureDesc.Width, TextureDesc.Height, 1, 1, 1, PF_A2B10G10R10, false, false, false ); D3D11TextureAllocated2D(*NewTexture); NewTexture->DoNoDeferDelete(); return NewTexture; }
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); }
FUnorderedAccessViewRHIRef FD3D11DynamicRHI::RHICreateUnorderedAccessView(FTextureRHIParamRef TextureRHI) { FD3D11TextureBase* Texture = GetD3D11TextureFromRHITexture(TextureRHI); D3D11_UNORDERED_ACCESS_VIEW_DESC UAVDesc; if (TextureRHI->GetTexture3D() != NULL) { FD3D11Texture3D* Texture3D = (FD3D11Texture3D*)Texture; UAVDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D; UAVDesc.Texture3D.MipSlice = 0; UAVDesc.Texture3D.FirstWSlice = 0; UAVDesc.Texture3D.WSize = Texture3D->GetSizeZ(); } else { UAVDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; UAVDesc.Texture2D.MipSlice = 0; } UAVDesc.Format = FindShaderResourceDXGIFormat((DXGI_FORMAT)GPixelFormats[TextureRHI->GetFormat()].PlatformFormat, false); TRefCountPtr<ID3D11UnorderedAccessView> UnorderedAccessView; VERIFYD3D11RESULT(Direct3DDevice->CreateUnorderedAccessView(Texture->GetResource(),&UAVDesc,(ID3D11UnorderedAccessView**)UnorderedAccessView.GetInitReference())); return new FD3D11UnorderedAccessView(UnorderedAccessView,Texture); }
FVertexShaderRHIRef FD3D11DynamicRHI::RHICreateVertexShader(const TArray<uint8>& Code) { check(Code.Num()); TRefCountPtr<ID3D11VertexShader> D3DShader; VERIFYD3D11RESULT(Direct3DDevice->CreateVertexShader((void*)Code.GetTypedData(),Code.Num() - 1,NULL,D3DShader.GetInitReference())); return new FD3D11VertexShader(D3DShader,Code); }
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); }
FBlendStateRHIRef FD3D11DynamicRHI::RHICreateBlendState(const FBlendStateInitializerRHI& Initializer) { D3D11_BLEND_DESC BlendDesc; FMemory::Memzero(&BlendDesc,sizeof(D3D11_BLEND_DESC)); BlendDesc.AlphaToCoverageEnable = false; BlendDesc.IndependentBlendEnable = Initializer.bUseIndependentRenderTargetBlendStates; static_assert(MaxSimultaneousRenderTargets <= D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, "Too many MRTs."); for(uint32 RenderTargetIndex = 0;RenderTargetIndex < MaxSimultaneousRenderTargets;++RenderTargetIndex) { const FBlendStateInitializerRHI::FRenderTarget& RenderTargetInitializer = Initializer.RenderTargets[RenderTargetIndex]; D3D11_RENDER_TARGET_BLEND_DESC& RenderTarget = BlendDesc.RenderTarget[RenderTargetIndex]; RenderTarget.BlendEnable = RenderTargetInitializer.ColorBlendOp != BO_Add || RenderTargetInitializer.ColorDestBlend != BF_Zero || RenderTargetInitializer.ColorSrcBlend != BF_One || RenderTargetInitializer.AlphaBlendOp != BO_Add || RenderTargetInitializer.AlphaDestBlend != BF_Zero || RenderTargetInitializer.AlphaSrcBlend != BF_One; RenderTarget.BlendOp = TranslateBlendOp(RenderTargetInitializer.ColorBlendOp); RenderTarget.SrcBlend = TranslateBlendFactor(RenderTargetInitializer.ColorSrcBlend); RenderTarget.DestBlend = TranslateBlendFactor(RenderTargetInitializer.ColorDestBlend); RenderTarget.BlendOpAlpha = TranslateBlendOp(RenderTargetInitializer.AlphaBlendOp); RenderTarget.SrcBlendAlpha = TranslateBlendFactor(RenderTargetInitializer.AlphaSrcBlend); RenderTarget.DestBlendAlpha = TranslateBlendFactor(RenderTargetInitializer.AlphaDestBlend); RenderTarget.RenderTargetWriteMask = ((RenderTargetInitializer.ColorWriteMask & CW_RED) ? D3D11_COLOR_WRITE_ENABLE_RED : 0) | ((RenderTargetInitializer.ColorWriteMask & CW_GREEN) ? D3D11_COLOR_WRITE_ENABLE_GREEN : 0) | ((RenderTargetInitializer.ColorWriteMask & CW_BLUE) ? D3D11_COLOR_WRITE_ENABLE_BLUE : 0) | ((RenderTargetInitializer.ColorWriteMask & CW_ALPHA) ? D3D11_COLOR_WRITE_ENABLE_ALPHA : 0); } FD3D11BlendState* BlendState = new FD3D11BlendState; VERIFYD3D11RESULT(Direct3DDevice->CreateBlendState(&BlendDesc,BlendState->Resource.GetInitReference())); return BlendState; }
void FD3D12CommandListManager::Create(ID3D12Device* InDirect3DDevice, D3D12_COMMAND_LIST_TYPE InCommandListType, uint32 NumCommandLists) { Direct3DDevice = InDirect3DDevice; CommandListType = InCommandListType; check(D3DCommandQueue.GetReference() == nullptr); check(ReadyLists.IsEmpty()); checkf(NumCommandLists <= 0xffff, TEXT("Exceeded maximum supported command lists")); D3D12_COMMAND_QUEUE_DESC CommandQueueDesc = {}; CommandQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; CommandQueueDesc.NodeMask = 0; CommandQueueDesc.Priority = 0; CommandQueueDesc.Type = CommandListType; VERIFYD3D11RESULT(Direct3DDevice->CreateCommandQueue(&CommandQueueDesc, IID_PPV_ARGS(D3DCommandQueue.GetInitReference()))); for (uint32 i = 0; i < FT_NumTypes; i++) { Fences[i].CreateFence(Direct3DDevice, 0); } for (uint32 i = 0; i < NumCommandLists; ++i) { FD3D12CommandListHandle hList = CreateCommandListHandle(); ReadyLists.Enqueue(hList); } }
/** Presents the swap chain checking the return result. */ bool FD3D11Viewport::PresentChecked(int32 SyncInterval) { HRESULT Result = S_OK; bool bNeedNativePresent = true; if (IsValidRef(CustomPresent)) { bNeedNativePresent = CustomPresent->Present(SyncInterval); } if (bNeedNativePresent) { // Present the back buffer to the viewport window. Result = SwapChain->Present(SyncInterval, 0); } // Detect a lost device. if(Result == DXGI_ERROR_DEVICE_REMOVED || Result == DXGI_ERROR_DEVICE_RESET || Result == DXGI_ERROR_DRIVER_INTERNAL_ERROR) { // This variable is checked periodically by the main thread. D3DRHI->bDeviceRemoved = true; } else { VERIFYD3D11RESULT(Result); } return bNeedNativePresent; }
void FD3D11DisjointTimeStampQuery::InitDynamicRHI() { D3D11_QUERY_DESC QueryDesc; QueryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT; QueryDesc.MiscFlags = 0; VERIFYD3D11RESULT(D3DRHI->GetDevice()->CreateQuery(&QueryDesc, DisjointQuery.GetInitReference())); }
FComputeShaderRHIRef FD3D11DynamicRHI::RHICreateComputeShader(const TArray<uint8>& Code) { check(Code.Num()); TRefCountPtr<ID3D11ComputeShader> D3DShader; // bGlobalUniformBufferUsed is in the last byte, see CompileD3D11Shader VERIFYD3D11RESULT(Direct3DDevice->CreateComputeShader((void*)Code.GetTypedData(),Code.Num() - 1,NULL,(ID3D11ComputeShader**)D3DShader.GetInitReference())); return new FD3D11ComputeShader(D3DShader, Code); }
void FD3D12Fence::CreateFence(ID3D12Device* pDirect3DDevice, uint64 InitialValue) { check(Fence == nullptr); VERIFYD3D11RESULT(pDirect3DDevice->CreateFence(InitialValue, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(Fence.GetInitReference()))); LastCompletedFence = Fence->GetCompletedValue(); CurrentFence = LastCompletedFence + 1; }
void FD3D11EventQuery::InitDynamicRHI() { D3D11_QUERY_DESC QueryDesc; QueryDesc.Query = D3D11_QUERY_EVENT; QueryDesc.MiscFlags = 0; VERIFYD3D11RESULT(D3DRHI->GetDevice()->CreateQuery(&QueryDesc,Query.GetInitReference())); // Initialize the query by issuing an initial event. IssueEvent(); }
FIndexBufferRHIRef FD3D11DynamicRHI::RHICreateIndexBuffer(uint32 Stride,uint32 Size,uint32 InUsage, FRHIResourceCreateInfo& CreateInfo) { // Explicitly check that the size is nonzero before allowing CreateIndexBuffer to opaquely fail. check(Size > 0); // Describe the index buffer. D3D11_BUFFER_DESC Desc; ZeroMemory( &Desc, sizeof( D3D11_BUFFER_DESC ) ); Desc.ByteWidth = Size; Desc.Usage = (InUsage & BUF_AnyDynamic) ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; Desc.BindFlags = D3D11_BIND_INDEX_BUFFER; Desc.CPUAccessFlags = (InUsage & BUF_AnyDynamic) ? D3D11_CPU_ACCESS_WRITE : 0; Desc.MiscFlags = 0; if (InUsage & BUF_UnorderedAccess) { Desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; } if(InUsage & BUF_DrawIndirect) { Desc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; } if (InUsage & BUF_ShaderResource) { Desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; } // If a resource array was provided for the resource, create the resource pre-populated D3D11_SUBRESOURCE_DATA InitData; D3D11_SUBRESOURCE_DATA* pInitData = NULL; if(CreateInfo.ResourceArray) { check(Size == CreateInfo.ResourceArray->GetResourceDataSize()); InitData.pSysMem = CreateInfo.ResourceArray->GetResourceData(); InitData.SysMemPitch = Size; InitData.SysMemSlicePitch = 0; pInitData = &InitData; } TRefCountPtr<ID3D11Buffer> IndexBufferResource; VERIFYD3D11RESULT(Direct3DDevice->CreateBuffer(&Desc,pInitData,IndexBufferResource.GetInitReference())); UpdateBufferStats(IndexBufferResource, true); if(CreateInfo.ResourceArray) { // Discard the resource array's contents. CreateInfo.ResourceArray->Discard(); } return new FD3D11IndexBuffer(IndexBufferResource, Stride, Size, InUsage); }
FD3D11Viewport::~FD3D11Viewport() { check(IsInRenderingThread()); // If the swap chain was in fullscreen mode, switch back to windowed before releasing the swap chain. // DXGI throws an error otherwise. VERIFYD3D11RESULT(SwapChain->SetFullscreenState(false,NULL)); FrameSyncEvent.ReleaseResource(); D3DRHI->Viewports.Remove(this); }
uint64 FD3D12Fence::Signal(ID3D12CommandQueue* pCommandQueue) { check(pCommandQueue != nullptr); VERIFYD3D11RESULT(pCommandQueue->Signal(Fence.GetReference(), CurrentFence)); // Save the current fence and increment it const uint64 SignaledFence = CurrentFence++; // Return the value that was signaled return SignaledFence; }
FUnorderedAccessViewRHIRef FD3D11DynamicRHI::RHICreateUnorderedAccessView(FStructuredBufferRHIParamRef StructuredBufferRHI, bool bUseUAVCounter, bool bAppendBuffer) { FD3D11StructuredBuffer* StructuredBuffer = ResourceCast(StructuredBufferRHI); 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); }
int32 FD3DGPUProfiler::RecordEventTimestamp(ID3D11Device* Direct3DDevice, ID3D11DeviceContext* Direct3DDeviceIMContext) { check(CurrentGPUProfile); D3D11_QUERY_DESC TimestampQueryDesc; TimestampQueryDesc.Query = D3D11_QUERY_TIMESTAMP; TimestampQueryDesc.MiscFlags = 0; TRefCountPtr<ID3D11Query> TimestampQuery; VERIFYD3D11RESULT(Direct3DDevice->CreateQuery(&TimestampQueryDesc,TimestampQuery.GetInitReference())); Direct3DDeviceIMContext->End(TimestampQuery); return CurrentGPUProfile->EventTimestampQueries.Add(TimestampQuery); }
bool FD3D11DynamicRHI::GetQueryData(ID3D11Query* Query,void* Data,SIZE_T DataSize,bool bWait, ERenderQueryType QueryType) { // Request the data from the query. HRESULT Result = Direct3DDeviceIMContext->GetData(Query,Data,DataSize,0); // Isn't the query finished yet, and can we wait for it? if ( Result == S_FALSE && bWait ) { SCOPE_CYCLE_COUNTER( STAT_RenderQueryResultTime ); uint32 IdleStart = FPlatformTime::Cycles(); double StartTime = FPlatformTime::Seconds(); do { Result = Direct3DDeviceIMContext->GetData(Query,Data,DataSize,0); // timer queries are used for Benchmarks which can stall a bit more double TimeoutValue = (QueryType == RQT_AbsoluteTime) ? 2.0 : 0.5; if((FPlatformTime::Seconds() - StartTime) > TimeoutValue) { UE_LOG(LogD3D11RHI, Log, TEXT("Timed out while waiting for GPU to catch up. (%.1f s)"), TimeoutValue); return false; } } while ( Result == S_FALSE ); GRenderThreadIdle[ERenderThreadIdleTypes::WaitingForGPUQuery] += FPlatformTime::Cycles() - IdleStart; GRenderThreadNumIdle[ERenderThreadIdleTypes::WaitingForGPUQuery]++; } if( Result == S_OK ) { return true; } else if(Result == S_FALSE && !bWait) { // Return failure if the query isn't complete, and waiting wasn't requested. return false; } else if( Result == DXGI_ERROR_DEVICE_REMOVED || Result == DXGI_ERROR_DEVICE_RESET || Result == DXGI_ERROR_DRIVER_INTERNAL_ERROR ) { bDeviceRemoved = true; return false; } else { VERIFYD3D11RESULT(Result); return false; } }
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); FD3D11VertexDeclaration* InVertexDeclaration = FD3D11DynamicRHI::ResourceCast(InVertexDeclarationRHI); FD3D11VertexShader* InVertexShader = FD3D11DynamicRHI::ResourceCast(InVertexShaderRHI); FD3D11PixelShader* InPixelShader = FD3D11DynamicRHI::ResourceCast(InPixelShaderRHI); FD3D11HullShader* InHullShader = FD3D11DynamicRHI::ResourceCast(InHullShaderRHI); FD3D11DomainShader* InDomainShader = FD3D11DynamicRHI::ResourceCast(InDomainShaderRHI); FD3D11GeometryShader* InGeometryShader = FD3D11DynamicRHI::ResourceCast(InGeometryShaderRHI); // 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."); }
FGeometryShaderRHIRef FD3D11DynamicRHI::RHICreateGeometryShaderWithStreamOutput(const TArray<uint8>& Code, const FStreamOutElementList& ElementList, uint32 NumStrides, const uint32* Strides, int32 RasterizedStream) { check(Code.Num()); FD3D11GeometryShader* Shader = new FD3D11GeometryShader; FMemoryReader Ar( Code, true ); Ar << Shader->ShaderResourceTable; int32 Offset = Ar.Tell(); const uint8* CodePtr = Code.GetData() + Offset; const size_t CodeSize = Code.Num() - Offset - 1; uint32 D3DRasterizedStream = RasterizedStream; if (RasterizedStream == -1) { D3DRasterizedStream = D3D11_SO_NO_RASTERIZED_STREAM; } D3D11_SO_DECLARATION_ENTRY StreamOutEntries[D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT]; for (int32 EntryIndex = 0; EntryIndex < ElementList.Num(); EntryIndex++) { StreamOutEntries[EntryIndex].Stream = ElementList[EntryIndex].Stream; StreamOutEntries[EntryIndex].SemanticName = ElementList[EntryIndex].SemanticName; StreamOutEntries[EntryIndex].SemanticIndex = ElementList[EntryIndex].SemanticIndex; StreamOutEntries[EntryIndex].StartComponent = ElementList[EntryIndex].StartComponent; StreamOutEntries[EntryIndex].ComponentCount = ElementList[EntryIndex].ComponentCount; StreamOutEntries[EntryIndex].OutputSlot = ElementList[EntryIndex].OutputSlot; } VERIFYD3D11RESULT( Direct3DDevice->CreateGeometryShaderWithStreamOutput( (void*)CodePtr, CodeSize, StreamOutEntries, ElementList.Num(), Strides, NumStrides, D3DRasterizedStream, NULL, Shader->Resource.GetInitReference() ) ); // bGlobalUniformBufferUsed is in the last byte, see CompileD3D11Shader Shader->bShaderNeedsGlobalConstantBuffer = Code[Code.Num() - 1] != 0; return Shader; }
FDepthStencilStateRHIRef FD3D11DynamicRHI::RHICreateDepthStencilState(const FDepthStencilStateInitializerRHI& Initializer) { FD3D11DepthStencilState* DepthStencilState = new FD3D11DepthStencilState; D3D11_DEPTH_STENCIL_DESC DepthStencilDesc; FMemory::Memzero(&DepthStencilDesc,sizeof(D3D11_DEPTH_STENCIL_DESC)); // depth part DepthStencilDesc.DepthEnable = Initializer.DepthTest != CF_Always || Initializer.bEnableDepthWrite; DepthStencilDesc.DepthWriteMask = Initializer.bEnableDepthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; DepthStencilDesc.DepthFunc = TranslateCompareFunction(Initializer.DepthTest); // stencil part DepthStencilDesc.StencilEnable = Initializer.bEnableFrontFaceStencil || Initializer.bEnableBackFaceStencil; DepthStencilDesc.StencilReadMask = Initializer.StencilReadMask; DepthStencilDesc.StencilWriteMask = Initializer.StencilWriteMask; DepthStencilDesc.FrontFace.StencilFunc = TranslateCompareFunction(Initializer.FrontFaceStencilTest); DepthStencilDesc.FrontFace.StencilFailOp = TranslateStencilOp(Initializer.FrontFaceStencilFailStencilOp); DepthStencilDesc.FrontFace.StencilDepthFailOp = TranslateStencilOp(Initializer.FrontFaceDepthFailStencilOp); DepthStencilDesc.FrontFace.StencilPassOp = TranslateStencilOp(Initializer.FrontFacePassStencilOp); if( Initializer.bEnableBackFaceStencil ) { DepthStencilDesc.BackFace.StencilFunc = TranslateCompareFunction(Initializer.BackFaceStencilTest); DepthStencilDesc.BackFace.StencilFailOp = TranslateStencilOp(Initializer.BackFaceStencilFailStencilOp); DepthStencilDesc.BackFace.StencilDepthFailOp = TranslateStencilOp(Initializer.BackFaceDepthFailStencilOp); DepthStencilDesc.BackFace.StencilPassOp = TranslateStencilOp(Initializer.BackFacePassStencilOp); } else { DepthStencilDesc.BackFace = DepthStencilDesc.FrontFace; } const bool bStencilOpIsKeep = Initializer.FrontFaceStencilFailStencilOp == SO_Keep && Initializer.FrontFaceDepthFailStencilOp == SO_Keep && Initializer.FrontFacePassStencilOp == SO_Keep && Initializer.BackFaceStencilFailStencilOp == SO_Keep && Initializer.BackFaceDepthFailStencilOp == SO_Keep && Initializer.BackFacePassStencilOp == SO_Keep; const bool bMayWriteStencil = Initializer.StencilWriteMask != 0 && !bStencilOpIsKeep; DepthStencilState->AccessType = (EDepthStencilAccessType)((Initializer.bEnableDepthWrite ? DSAT_Writable : DSAT_ReadOnlyDepth) | (bMayWriteStencil ? DSAT_Writable : DSAT_ReadOnlyStencil)); VERIFYD3D11RESULT(Direct3DDevice->CreateDepthStencilState(&DepthStencilDesc,DepthStencilState->Resource.GetInitReference())); return DepthStencilState; }
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); }
FRasterizerStateRHIRef FD3D11DynamicRHI::RHICreateRasterizerState(const FRasterizerStateInitializerRHI& Initializer) { D3D11_RASTERIZER_DESC RasterizerDesc; FMemory::Memzero(&RasterizerDesc,sizeof(D3D11_RASTERIZER_DESC)); RasterizerDesc.CullMode = TranslateCullMode(Initializer.CullMode); RasterizerDesc.FillMode = TranslateFillMode(Initializer.FillMode); RasterizerDesc.SlopeScaledDepthBias = Initializer.SlopeScaleDepthBias; RasterizerDesc.FrontCounterClockwise = true; RasterizerDesc.DepthBias = FMath::FloorToInt(Initializer.DepthBias * (float)(1 << 24)); RasterizerDesc.DepthClipEnable = true; RasterizerDesc.MultisampleEnable = Initializer.bAllowMSAA; RasterizerDesc.ScissorEnable = true; FD3D11RasterizerState* RasterizerState = new FD3D11RasterizerState; VERIFYD3D11RESULT(Direct3DDevice->CreateRasterizerState(&RasterizerDesc,RasterizerState->Resource.GetInitReference())); return RasterizerState; }
void FD3D12Fence::WaitForFence(uint64 FenceValue) { SCOPE_CYCLE_COUNTER(STAT_D3D12WaitForFenceTime); check(Fence != nullptr); if (IsFenceFinished(FenceValue)) return; // We must wait. Do so with an event handler so we don't oversleep. VERIFYD3D11RESULT(Fence->SetEventOnCompletion(FenceValue, hFenceCompleteEvent)); // Wait for the event to complete (the event is automatically reset afterwards) const uint32 WaitResult = WaitForSingleObject(hFenceCompleteEvent, INFINITE); check(0 == WaitResult); LastCompletedFence = FenceValue; }
FGeometryShaderRHIRef FD3D11DynamicRHI::RHICreateGeometryShader(const TArray<uint8>& Code) { check(Code.Num()); FD3D11GeometryShader* Shader = new FD3D11GeometryShader; FMemoryReader Ar( Code, true ); Ar << Shader->ShaderResourceTable; int32 Offset = Ar.Tell(); const uint8* CodePtr = Code.GetData() + Offset; const size_t CodeSize = Code.Num() - Offset - 1; VERIFYD3D11RESULT( Direct3DDevice->CreateGeometryShader( (void*)CodePtr, CodeSize, NULL, Shader->Resource.GetInitReference() ) ); // bGlobalUniformBufferUsed is in the last byte, see CompileD3D11Shader Shader->bShaderNeedsGlobalConstantBuffer = Code[Code.Num() - 1] != 0; return Shader; }
bool FD3D11Viewport::Present(bool bLockToVsync) { bool bNativelyPresented = true; #if D3D11_WITH_DWMAPI // We can't call Present if !bIsValid, as it waits a window message to be processed, but the main thread may not be pumping the message handler. if(bIsValid) { // Check if the viewport's swap chain has been invalidated by DXGI. BOOL bSwapChainFullscreenState; TRefCountPtr<IDXGIOutput> SwapChainOutput; VERIFYD3D11RESULT(SwapChain->GetFullscreenState(&bSwapChainFullscreenState,SwapChainOutput.GetInitReference())); // Can't compare BOOL with bool... if ( (!!bSwapChainFullscreenState) != bIsFullscreen ) { bIsValid = false; // Minimize the window. // use SW_FORCEMINIMIZE if the messaging thread is likely to be blocked for a sizeable period. // SW_FORCEMINIMIZE also prevents the minimize animation from playing. ::ShowWindow(WindowHandle,SW_MINIMIZE); } } // When desktop composition is enabled, locking to vsync via the Present // call is unreliable. Instead, communicate with the desktop window manager // directly to enable vsync. const bool bSyncWithDWM = bLockToVsync && !bIsFullscreen && RHIConsoleVariables::bSyncWithDWM && IsCompositionEnabled(); if (bSyncWithDWM) { PresentWithVsyncDWM(); } else #endif //D3D11_WITH_DWMAPI { // Present the back buffer to the viewport window. bNativelyPresented = PresentChecked(bLockToVsync ? RHIConsoleVariables::SyncInterval : 0); } return bNativelyPresented; }
FRenderQueryRHIRef FD3D11DynamicRHI::RHICreateRenderQuery(ERenderQueryType QueryType) { TRefCountPtr<ID3D11Query> Query; D3D11_QUERY_DESC Desc; if(QueryType == RQT_Occlusion) { Desc.Query = D3D11_QUERY_OCCLUSION; } else if(QueryType == RQT_AbsoluteTime) { Desc.Query = D3D11_QUERY_TIMESTAMP; } else { check(0); } Desc.MiscFlags = 0; VERIFYD3D11RESULT(Direct3DDevice->CreateQuery(&Desc,Query.GetInitReference())); return new FD3D11OcclusionQuery(Query, QueryType); }
FVertexShaderRHIRef FD3D11DynamicRHI::RHICreateVertexShader(const TArray<uint8>& Code) { check(Code.Num()); FD3D11VertexShader* Shader = new FD3D11VertexShader; FMemoryReader Ar( Code, true ); Ar << Shader->ShaderResourceTable; int32 Offset = Ar.Tell(); const uint8* CodePtr = Code.GetData() + Offset; const size_t CodeSize = Code.Num() - Offset - 5; VERIFYD3D11RESULT( Direct3DDevice->CreateVertexShader( (void*)CodePtr, CodeSize, NULL, Shader->Resource.GetInitReference() ) ); // bGlobalUniformBufferUsed and resource counts are packed in the last few bytes, see CompileD3D11Shader Shader->bShaderNeedsGlobalConstantBuffer = Code[Code.Num() - 5] != 0; // TEMP Shader->Code = Code; Shader->Offset = Offset; return Shader; }