#include "DX12GraphicsApi.h" #include #include #include #include #include "Camera3D.h" #include "d3dx12.h" #include "DLLRegister.h" #include "DX12BLASModel.h" #include "DX12CommandQueue.h" #include "DX12HitShader.h" #include "DX12MissShader.h" #include "DX12RayGenShader.h" #include "DX12Shader.h" #include "DX12Texture.h" #include "DX12TLAS.h" #include "Globals.h" #include "Image.h" #include "Model3D.h" #include "Model3DList.h" #include "Screen.h" #include "TextureList.h" #include "TextureModel.h" #include "Window.h" #include "World3D.h" using namespace Framework; DirectX12::DirectX12() : GraphicsApi(DIRECTX12), debug(0), infoQueue(0), directCommandQueue(0), swapChain(0), backBufferIndex(0), tearing(0), signature(0), uiTexture(0), texturRegister(new TextureList()), blasModels(0), worldTLAS(0), worldShaderBindingTables(0), lastTLASId(-1), lastModelId(-1), defaultRenderTarget(0), defaultKamera(0), cameraCount(0), rayGenSettingsBuffer(0), device(0), pfnD3D12SerializeRootSignature(0), pipeline(0), globalDescriptorHeap(0), defaultHitGroup(0), defaultRayGenerationShaderFunction(0) { for (int i = 0; i < 2; i++) backBuffer[i] = 0; } DirectX12::~DirectX12() { if (blasModels) { for (int i = 0; i <= lastModelId; i++) { if (blasModels[i]) blasModels[i]->release(); } delete[] blasModels; } if (worldTLAS) { for (int i = 0; i <= lastTLASId; i++) { if (worldTLAS[i]) worldTLAS[i]->release(); } delete[] worldTLAS; } if (worldShaderBindingTables) { for (int i = 0; i <= lastTLASId; i++) { if (worldShaderBindingTables[i]) worldShaderBindingTables[i]->release(); } delete[] worldShaderBindingTables; } if (globalDescriptorHeap) { globalDescriptorHeap->release(); } if (pipeline) { pipeline->release(); } if (directCommandQueue) { directCommandQueue->flush(); directCommandQueue->release(); } if (rayGenSettingsBuffer) { rayGenSettingsBuffer->release(); } texturRegister->release(); if (uiTexture) uiTexture->release(); if (defaultKamera) defaultKamera->release(); if (defaultRenderTarget) defaultRenderTarget->release(); if (signature) signature->Release(); for (int i = 0; i < 2; i++) { if (backBuffer[i]) backBuffer[i]->Release(); } if (swapChain) swapChain->Release(); if (infoQueue) infoQueue->Release(); if (device) { device->Release(); getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d12.dll"); } if (debug) debug->Release(); } void DirectX12::updateBottomLevelAccelerationStructure() { cs.lock(); bool updateRequired = 0; for (const Model3DData* model : *modelList->zModels()) { if (model->wasIndexBufferChanged() || model->wasVertexBufferChanged()) { updateRequired = true; break; } } int bufferCount = 0; if (updateRequired) { for (const Model3DData* model : *modelList->zModels()) { int id = model->getId(); blasModels[id]->calculateBuffers(); bufferCount += blasModels[id]->getBufferCount(); } } cs.unlock(); } void Framework::DirectX12::renderKamera( Cam3D* zKamera, DX12Texture* zTarget, bool guiVisible) { updateBottomLevelAccelerationStructure(); if (guiVisible) { uiTexture->updateTextur(); } if (!pipeline) { setPipeline(new DX12Pipeline()); } directCommandQueue->zCommandList()->RSSetViewports( 1, (D3D12_VIEWPORT*)zKamera->zViewPort()); Mat4 identity = Mat4::identity(); World3D* w = zKamera->zWorld(); if (w->getId() < 0) { w->setId(++lastTLASId); DX12TLAS** tmp = new DX12TLAS*[lastTLASId + 1]; if (lastTLASId) { memcpy(tmp, worldTLAS, sizeof(DX12TLAS*) * lastTLASId); } tmp[lastTLASId] = new DX12TLAS(device, directCommandQueue); delete[] worldTLAS; worldTLAS = tmp; DX12ShaderBindingTable** tmpsbts = new DX12ShaderBindingTable*[lastTLASId + 1]; if (lastTLASId) { memcpy(tmpsbts, worldShaderBindingTables, sizeof(DX12ShaderBindingTable*) * lastTLASId); } tmpsbts[lastTLASId] = pipeline->createShaderBindingTable(); delete[] worldShaderBindingTables; worldShaderBindingTables = tmpsbts; } else if (worldShaderBindingTables[w->getId()]->zPipeline() != pipeline) { worldShaderBindingTables[w->getId()]->release(); worldShaderBindingTables[w->getId()] = pipeline->createShaderBindingTable(); } DX12TLAS* tlas = worldTLAS[w->getId()]; DX12ShaderBindingTable* sbt = worldShaderBindingTables[w->getId()]; tlas->startUpdate(); sbt->startUpdate(); int objectIndex = 0; int instanceIndex = 0; w->render([this, &tlas, &objectIndex, &instanceIndex, &identity, &sbt]( Model3D* obj) { obj->calculateMatrices(identity, matrixBuffer); int modelId = obj->zModelData()->getId(); DX12BLASModel* blasModel = blasModels[modelId]; blasModel->calculateBuffers(); ArrayIterator boneIds = blasModel->zBoneIds()->begin(); for (const DX12BLAS* blas : *blasModel->zBLAS()) { D3D12_RAYTRACING_INSTANCE_DESC* desc = tlas->nextInstanceDesc(); desc->InstanceID = objectIndex; desc->InstanceContributionToHitGroupIndex = objectIndex; desc->Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE; desc->InstanceMask = 0xFF; desc->AccelerationStructure = blas->zResultBuffer()->zBuffer()->GetGPUVirtualAddress(); memcpy(desc->Transform, &matrixBuffer[boneIds.val()], sizeof(float) * 12); boneIds++; instanceIndex++; } fillShaderBindingTable(sbt, obj, objectIndex); objectIndex++; }); tlas->endUpdate(); settings.inverseProjection = zKamera->getInverseProjectionMatrix(); settings.inverseView = zKamera->getInverseViewMatrix(); settings.minDistance = zKamera->getMinDistance(); settings.maxDistance = zKamera->getMaxDistance(); settings.useRays = 1; settings.renderGui = (int)guiVisible; rayGenSettingsBuffer->setData(&settings, 1); rayGenSettingsBuffer->copyToGPU(sizeof(settings)); if (defaultRayGenerationShaderFunction) { globalDescriptorHeap->updateTextureInput( 0, DX12_SHADER_REGISTER_U_UNORDERED_ACCESS, zTarget); globalDescriptorHeap->updateTLASInput( 3, DX12_SHADER_REGISTER_T_SHADER_RESOURCE, tlas); } sbt->setGlobalDescriptorHeap(globalDescriptorHeap); sbt->endUpdate(device, directCommandQueue); ID3D12DescriptorHeap* heaps[] = {globalDescriptorHeap->zDescriptorHeap()}; directCommandQueue->zCommandList()->SetDescriptorHeaps(1, heaps); D3D12_DISPATCH_RAYS_DESC desc; sbt->fillDispatchRaysDesc(&desc); desc.Width = zTarget->zImage()->getWidth(); desc.Height = zTarget->zImage()->getHeight(); desc.Depth = 1; directCommandQueue->zCommandList()->SetPipelineState1( pipeline->zPipelineState()); directCommandQueue->zCommandList()->DispatchRays(&desc); } void Framework::DirectX12::initializePipeline() { if (pipeline->getShaders().getEntryCount() == 0) { // add default shaders DX12Shader* rayGenShader = new DX12Shader(DX12DefaultRayGenerationShaderBytes, sizeof(DX12DefaultRayGenerationShaderBytes)); // RayGen from RayGen.hlsl DX12ShaderSignature* rayGenSignature = new DX12ShaderSignature(); rayGenSignature->addRegisterUsageLinkedToDescriptorHeap( 0, DX12_SHADER_REGISTER_U_UNORDERED_ACCESS, 0); rayGenSignature->addRegisterUsageLinkedToDescriptorHeap( 1, DX12_SHADER_REGISTER_U_UNORDERED_ACCESS, 1); rayGenSignature->addRegisterUsageLinkedToDescriptorHeap( 2, DX12_SHADER_REGISTER_B_CONST_BUFFER, 0); rayGenSignature->addRegisterUsageLinkedToDescriptorHeap( 3, DX12_SHADER_REGISTER_T_SHADER_RESOURCE, 0); defaultRayGenerationShaderFunction = new DX12ShaderFunction( "RayGen", rayGenSignature, DX12_SHADER_FUNCTION_TYPE_RAY_GEN); rayGenShader->addFunction(defaultRayGenerationShaderFunction); pipeline->addShader(rayGenShader); DX12Shader* missShader = new DX12Shader( DX12DefaultMissShaderBytes, sizeof(DX12DefaultMissShaderBytes)); // Miss from Miss.hlsl missShader->addFunction(new DX12ShaderFunction( "Miss", new DX12ShaderSignature(), DX12_SHADER_FUNCTION_TYPE_MISS)); pipeline->addShader(missShader); DX12Shader* hitShader = new DX12Shader( DX12DefaultHitShaderBytes, sizeof(DX12DefaultHitShaderBytes)); // ClosestHit from Hit.hlsl DX12ShaderFunction* closestHitFunction = new DX12ShaderFunction("ClosestHit", new DX12ShaderSignature(), DX12_SHADER_FUNCTION_TYPE_CLOSEST_HIT); hitShader->addFunction(closestHitFunction); pipeline->addShader(hitShader); defaultHitGroup = new DX12ShaderHitGroup("HitGroup"); defaultHitGroup->setAttributeSize(8); defaultHitGroup->setPayloadSize(16); defaultHitGroup->setClosestHitShaderFunction(closestHitFunction); pipeline->addHitGroup(defaultHitGroup); pipeline->setMaxRecursionDepth(10); } pipeline->createPipelineState(device, pfnD3D12SerializeRootSignature); } void Framework::DirectX12::initializeGlobalDescriptorHeap() { globalDescriptorHeap->addTextureInput( DX12_SHADER_REGISTER_U_UNORDERED_ACCESS, defaultRenderTarget); globalDescriptorHeap->addTextureInput( DX12_SHADER_REGISTER_U_UNORDERED_ACCESS, uiTexture); globalDescriptorHeap->addBufferInput( DX12_SHADER_REGISTER_B_CONST_BUFFER, rayGenSettingsBuffer); globalDescriptorHeap->addTLASInput( DX12_SHADER_REGISTER_T_SHADER_RESOURCE, 0); globalDescriptorHeap->updateDescriptorHeap(device); } void Framework::DirectX12::fillShaderBindingTable( DX12ShaderBindingTable* zShaderBindingTable, Model3D* zModel, int instanceIndex) { if (defaultHitGroup) { zShaderBindingTable->addHitGroup(defaultHitGroup); } } typedef HRESULT(__stdcall* CreateDXGIFactory2Function)(UINT, REFIID, void**); typedef HRESULT(__stdcall* D3D12CreateDeviceFunction)( IDXGIAdapter*, D3D_FEATURE_LEVEL, REFIID, void**); typedef HRESULT(__stdcall* D3D12GetDebugInterfaceFunction)(REFIID, void**); typedef HRESULT(__stdcall* DXGIGetDebugInterface1Function)( UINT Flags, REFIID riid, _COM_Outptr_ void** pDebug); void DirectX12::initialize( NativeWindow* fenster, Vec2 backBufferSize, bool fullScreen) { GraphicsApi::initialize(fenster, backBufferSize, fullScreen); #ifdef _DEBUG if (debugDX) { HINSTANCE pixDebugger = getDLLRegister()->loadDLL( "WinPixGpuCapturer.dll", "C:\\Program Files\\Microsoft PIX\\2603.25\\WinPixGpuCapturer.dll"); } #endif HINSTANCE dxgiDLL = getDLLRegister()->loadDLL("dxgi.dll", "dxgi.dll"); if (!dxgiDLL) { WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text("dxgi.dll konnte nicht gefunden werden."), MB_ICONERROR); return; } HINSTANCE d3d12DLL = getDLLRegister()->loadDLL("d3d12.dll", "d3d12.dll"); if (!d3d12DLL) { getDLLRegister()->releaseDLL("dxgi.dll"); WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text("DirectX 12 konnte nicht gefunden werden."), MB_ICONERROR); return; } pfnD3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)GetProcAddress( d3d12DLL, "D3D12SerializeRootSignature"); if (!pfnD3D12SerializeRootSignature) { getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d12.dll"); WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text( "Der Einstiegspunkt D3D12SerializeRootSignature fon d3d12.dll " "konnte nicht gefunden werden."), MB_ICONERROR); return; } // CreateDXGIFactory2 CreateDXGIFactory2Function createFactory = (CreateDXGIFactory2Function)GetProcAddress( dxgiDLL, "CreateDXGIFactory2"); if (!createFactory) { getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d12.dll"); WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text( "Der Einstiegspunkt CreateDXGIFactory2 fon dxgi.dll konnte " "nicht gefunden werden."), MB_ICONERROR); return; } // D3D12CreateDevice D3D12CreateDeviceFunction createDevice = (D3D12CreateDeviceFunction)GetProcAddress( d3d12DLL, "D3D12CreateDevice"); if (!createDevice) { getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d12.dll"); WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text("Der Einstiegspunkt D3D12CreateDevice fon DirectX 12 " "konnte nicht gefunden werden."), MB_ICONERROR); return; } // D3D12SerializeVersionedRootSignature PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE d3d12svrsf = (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)GetProcAddress( d3d12DLL, "D3D12SerializeVersionedRootSignature"); // D3D12SerializeRootSignature PFN_D3D12_SERIALIZE_ROOT_SIGNATURE d3d12srsf = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)GetProcAddress( d3d12DLL, "D3D12SerializeRootSignature"); bool debugDXGI = 0; #ifdef _DEBUG IDXGIInfoQueue* dxgiInfoQueue; if (debugDX) { // D3D12GetDebugInterface D3D12GetDebugInterfaceFunction getDebugInterface = (D3D12GetDebugInterfaceFunction)GetProcAddress( d3d12DLL, "D3D12GetDebugInterface"); if (SUCCEEDED(getDebugInterface(__uuidof(ID3D12Debug), (void**)&debug))) debug->EnableDebugLayer(); // DXGIGetDebugInterface1 DXGIGetDebugInterface1Function dxgiDebugInterface = (DXGIGetDebugInterface1Function)GetProcAddress( dxgiDLL, "DXGIGetDebugInterface1"); if (SUCCEEDED(dxgiDebugInterface( 0, __uuidof(IDXGIInfoQueue), (void**)&dxgiInfoQueue))) debugDXGI = 1; } #endif IDXGIFactory6* factory; UINT createFactoryFlags = 0; #if defined(_DEBUG) if (debugDX && debugDXGI) createFactoryFlags = DXGI_CREATE_FACTORY_DEBUG; #endif HRESULT res = createFactory( createFactoryFlags, __uuidof(IDXGIFactory6), (void**)&factory); if (FAILED(res)) { getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d12.dll"); Logging::error() << "ERROR DXGI: createFactory returned " << res << "\n"; WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text("createFactory ist Fehlgeschlagen."), MB_ICONERROR); return; } IDXGIAdapter1* adapter = 0; for (UINT adapterID = 0; DXGI_ERROR_NOT_FOUND != factory->EnumAdapterByGpuPreference(adapterID, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, __uuidof(IDXGIAdapter1), (void**)&adapter); ++adapterID) { DXGI_ADAPTER_DESC1 desc; adapter->GetDesc1(&desc); if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) { adapter->Release(); // Don't select the Basic Render Driver adapter. continue; } // Check to see if the adapter supports Direct3D 12, but don't create // the actual device yet. if (SUCCEEDED(createDevice(adapter, D3D_FEATURE_LEVEL_12_1, _uuidof(ID3D12Device), nullptr))) { char buff[256] = {}; printf_s(buff, L"Direct3D Adapter (%u): VID:%04X, PID:%04X - %ls\n", adapterID, desc.VendorId, desc.DeviceId, desc.Description); Logging::info() << buff; break; } adapter->Release(); } if (!adapter) { if (FAILED(factory->EnumWarpAdapter( _uuidof(IDXGIAdapter1), (void**)&adapter))) Logging::error() << "ERROR: WARP12 not available. Enable the 'Graphics " "Tools' optional feature"; } if (!adapter) { factory->Release(); getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d12.dll"); WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text("Es wurde keine passende Grafigkarte gefunden."), MB_ICONERROR); return; } res = createDevice(adapter, D3D_FEATURE_LEVEL_12_1, __uuidof(ID3D12Device5), (void**)&device); adapter->Release(); if (FAILED(res)) { factory->Release(); getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d12.dll"); Logging::error() << "ERROR: createDevice returned " << res << "\n"; WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text("createDevice ist Fehlgeschlagen."), MB_ICONERROR); return; } D3D12_FEATURE_DATA_D3D12_OPTIONS5 featureSupportData = {}; device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &featureSupportData, sizeof(featureSupportData)); if (featureSupportData.RaytracingTier < D3D12_RAYTRACING_TIER_1_0) { device->Release(); factory->Release(); getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d12.dll"); Logging::error() << "ERROR: Raytracing is not available\n"; WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text("Raytracing ist nicht verfügbar. DirectX12 kann nicht " "verwendet werden."), MB_ICONERROR); return; } res = device->QueryInterface(__uuidof(ID3D12InfoQueue), (void**)&infoQueue); if (SUCCEEDED(res)) { if (debugDX) { infoQueue->SetBreakOnSeverity( D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE); infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE); infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, TRUE); } // Suppress individual messages by their ID D3D12_MESSAGE_ID DenyIds[] = { // D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE, // // I'm really not sure how to avoid this message. D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE, // This warning occurs when // using capture frame while // graphics debugging. D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE, // This warning occurs // when using capture // frame while graphics // debugging. }; D3D12_INFO_QUEUE_FILTER NewFilter = {}; NewFilter.DenyList.NumSeverities = 0; //_countof( Severities ); NewFilter.DenyList.pSeverityList = 0; // Severities; NewFilter.DenyList.NumIDs = _countof(DenyIds); NewFilter.DenyList.pIDList = DenyIds; infoQueue->PushStorageFilter(&NewFilter); } directCommandQueue = new DX12DirectCommandQueue(device); settings.minDistance = 0.0f; settings.maxDistance = 100000.f; settings.renderGui = 0; settings.useRays = 0; rayGenSettingsBuffer = new DX12Buffer(1, device, dynamic_cast(directCommandQueue->getThis()), D3D12_RESOURCE_FLAG_NONE); rayGenSettingsBuffer->setLength( ROUND_UP_POWER_OF_2(sizeof(RayGenerationSettings), 256)); rayGenSettingsBuffer->setData(&settings, 1); rayGenSettingsBuffer->copyToGPU(sizeof(RayGenerationSettings)); IDXGIFactory5* fac5 = 0; factory->QueryInterface(__uuidof(IDXGIFactory5), (void**)&fac5); if (fac5) { res = fac5->CheckFeatureSupport( DXGI_FEATURE_PRESENT_ALLOW_TEARING, &tearing, sizeof(tearing)); if (FAILED(res)) tearing = 0; fac5->Release(); } DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; swapChainDesc.Width = backBufferSize.x; swapChainDesc.Height = backBufferSize.y; swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; swapChainDesc.Stereo = FALSE; swapChainDesc.SampleDesc = {1, 0}; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.BufferCount = 2; swapChainDesc.Scaling = DXGI_SCALING_STRETCH; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; swapChainDesc.Flags = tearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0; IDXGISwapChain1* tmpSwapChain; res = factory->CreateSwapChainForHwnd(directCommandQueue->zQueue(), fenster->getWindowHandle(), &swapChainDesc, 0, 0, &tmpSwapChain); if (FAILED(res)) { factory->Release(); Logging::error() << "ERROR: CreateSwapChainForHwnd returned " << res << "\n"; WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text("CreateSwapChainForHwnd ist Fehlgeschlagen."), MB_ICONERROR); return; } res = tmpSwapChain->QueryInterface( __uuidof(IDXGISwapChain4), (void**)&swapChain); tmpSwapChain->Release(); if (FAILED(res)) { factory->Release(); Logging::error() << "ERROR: QueryInterface returned " << res << "\n"; WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text("QueryInterface ist Fehlgeschlagen."), MB_ICONERROR); return; } factory->MakeWindowAssociation( fenster->getWindowHandle(), DXGI_MWA_NO_ALT_ENTER); for (int i = 0; i < 2; i++) { ID3D12Resource* backBuffer; res = swapChain->GetBuffer( i, __uuidof(ID3D12Resource), (void**)&backBuffer); if (FAILED(res)) { factory->Release(); Logging::error() << "ERROR: GetBuffer returned " << res << "\n"; WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text("GetBuffer ist Fehlgeschlagen."), MB_ICONERROR); return; } this->backBuffer[i] = backBuffer; } Image* renderTargetImage = new Image(); renderTargetImage->newImage(backBufferSize.x, backBufferSize.y, 0); defaultRenderTarget = dynamic_cast( createOrGetTexture("_f_RenderTarget", renderTargetImage, GPU_TO_RAM)); defaultRenderTarget->updateTextur(); Image* renderB = new Image(1); renderB->setAlpha3D(1); renderB->newImage(this->backBufferSize.x, this->backBufferSize.y, 0); uiTexture = createOrGetTexture("_f_Render_Image", renderB, RAM_TO_GPU); D3D12_FEATURE_DATA_ROOT_SIGNATURE featureData = {}; featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1; if (FAILED(device->CheckFeatureSupport( D3D12_FEATURE_ROOT_SIGNATURE, &featureData, sizeof(featureData)))) featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_0; D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS; D3D12_DESCRIPTOR_RANGE1 range[2]; range[0].NumDescriptors = 5; range[0].BaseShaderRegister = 0; range[0].RegisterSpace = 0; range[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; range[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; range[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE; range[1].NumDescriptors = 1; range[1].BaseShaderRegister = 0; range[1].RegisterSpace = 0; range[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; range[1].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; range[1].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE; D3D12_ROOT_PARAMETER1 rootParameters[1]; rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; rootParameters[0].DescriptorTable.NumDescriptorRanges = 2; rootParameters[0].DescriptorTable.pDescriptorRanges = range; D3D12_STATIC_SAMPLER_DESC sampler = {}; sampler.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER; sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_BORDER; sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_BORDER; sampler.MipLODBias = 0; sampler.MaxAnisotropy = 0; sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; sampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; sampler.MinLOD = 0.0f; sampler.MaxLOD = D3D12_FLOAT32_MAX; sampler.ShaderRegister = 0; sampler.RegisterSpace = 0; sampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; D3D12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDescription; rootSignatureDescription.Version = D3D_ROOT_SIGNATURE_VERSION_1_1; rootSignatureDescription.Desc_1_1.NumParameters = 1; rootSignatureDescription.Desc_1_1.pParameters = rootParameters; rootSignatureDescription.Desc_1_1.NumStaticSamplers = 1; rootSignatureDescription.Desc_1_1.pStaticSamplers = &sampler; rootSignatureDescription.Desc_1_1.Flags = rootSignatureFlags; ID3DBlob* rootSignature; ID3DBlob* error; res = D3DX12SerializeVersionedRootSignature(&rootSignatureDescription, featureData.HighestVersion, &rootSignature, &error, d3d12svrsf, d3d12srsf); if (FAILED(res)) { factory->Release(); Logging::error() << "ERROR: D3DX12SerializeVersionedRootSignature returned " << res << "\n"; WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text( "D3DX12SerializeVersionedRootSignature ist Fehlgeschlagen."), MB_ICONERROR); if (error) error->Release(); return; } res = device->CreateRootSignature(0, rootSignature->GetBufferPointer(), rootSignature->GetBufferSize(), __uuidof(ID3D12RootSignature), (void**)&signature); if (FAILED(res)) { factory->Release(); Logging::error() << "ERROR: CreateRootSignature returned " << res << "\n"; WMessageBox(fenster->getWindowHandle(), new Text("Fehler"), new Text("CreateRootSignature ist Fehlgeschlagen."), MB_ICONERROR); return; } rootSignature->Release(); D3D12_RASTERIZER_DESC rdesc; rdesc.FillMode = D3D12_FILL_MODE_SOLID; rdesc.CullMode = D3D12_CULL_MODE_BACK; rdesc.FrontCounterClockwise = 0; rdesc.DepthBias = 0; rdesc.DepthBiasClamp = 0.f; rdesc.SlopeScaledDepthBias = 0.f; rdesc.DepthClipEnable = 1; rdesc.MultisampleEnable = 0; rdesc.AntialiasedLineEnable = 0; rdesc.ForcedSampleCount = 0; rdesc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; uiTexture->updateTextur(); directCommandQueue->execute(); factory->Release(); } void DirectX12::beginFrame(bool fill2D, bool fill3D, int fillColor) { cs.lock(); cameraCount = 0; D3D12_RESOURCE_BARRIER barrier; ZeroMemory(&barrier, sizeof(barrier)); barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barrier.Transition.pResource = this->backBuffer[backBufferIndex]; barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; directCommandQueue->zCommandList()->ResourceBarrier(1, &barrier); if (fill2D) uiTexture->zImage()->setColor(fillColor); CD3DX12_RESOURCE_BARRIER transition = CD3DX12_RESOURCE_BARRIER::Transition(defaultRenderTarget->zResource(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); directCommandQueue->zCommandList()->ResourceBarrier(1, &transition); } void DirectX12::renderKamera(Cam3D* zKamera) { cameraCount++; renderKamera(zKamera, defaultRenderTarget, true); } void Framework::DirectX12::renderKamera(Cam3D* zKamera, Texture* zTarget) { cameraCount++; renderKamera(zKamera, dynamic_cast(zTarget), false); } void DirectX12::presentFrame() { if (cameraCount == 0) { if (!defaultKamera) { defaultKamera = new Cam3D(); defaultKamera->setWorld(new World3D()); defaultKamera->setScreenSize(backBufferSize); } renderKamera(defaultKamera); } CD3DX12_RESOURCE_BARRIER transition = CD3DX12_RESOURCE_BARRIER::Transition(defaultRenderTarget->zResource(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE); directCommandQueue->zCommandList()->ResourceBarrier(1, &transition); transition = CD3DX12_RESOURCE_BARRIER::Transition(backBuffer[backBufferIndex], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_DEST); directCommandQueue->zCommandList()->ResourceBarrier(1, &transition); directCommandQueue->zCommandList()->CopyResource( backBuffer[backBufferIndex], defaultRenderTarget->zResource()); transition = CD3DX12_RESOURCE_BARRIER::Transition(backBuffer[backBufferIndex], D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_RENDER_TARGET); directCommandQueue->zCommandList()->ResourceBarrier(1, &transition); // Indicate that the back buffer will now be used to present. transition = CD3DX12_RESOURCE_BARRIER::Transition(backBuffer[backBufferIndex], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); directCommandQueue->zCommandList()->ResourceBarrier(1, &transition); directCommandQueue->execute(); swapChain->Present(0, 0); backBufferIndex = swapChain->GetCurrentBackBufferIndex(); cs.unlock(); } Texture* DirectX12::createOrGetTexture( const char* name, Image* b, TextureDirection dir) { if (!device) { if (b) b->release(); return 0; } if (texturRegister->hasTexture(name)) { Texture* ret = texturRegister->getTexture(name); if (b) ret->setImageZ(b); return ret; } cs.lock(); Texture* ret = new DX12Texture(device, directCommandQueue, dir); if (b) ret->setImageZ(b); texturRegister->addTexture(dynamic_cast(ret->getThis()), name); ret->updateTextur(); // directCommandQueue->execute(); cs.unlock(); return ret; } Image* DirectX12::zUIRenderImage() const { return uiTexture ? uiTexture->zImage() : 0; } DXBuffer* DirectX12::createStructuredBuffer(int eSize) { return new DX12Buffer(eSize, device, dynamic_cast(directCommandQueue->getThis()), D3D12_RESOURCE_FLAG_NONE); } Model3DData* Framework::DirectX12::createModel(const char* name) { cs.lock(); Model3DData* result = GraphicsApi::createModel(name); lastModelId = result->getId(); if (result) { DX12BLASModel** newBlasModels = new DX12BLASModel*[lastModelId + 1]; if (lastModelId > 0) { memcpy(newBlasModels, blasModels, sizeof(DX12BLASModel*) * lastModelId); } newBlasModels[lastModelId] = new DX12BLASModel(result, device, directCommandQueue); delete[] blasModels; blasModels = newBlasModels; } cs.unlock(); return result; } void Framework::DirectX12::setPipeline(DX12Pipeline* pipeline) { if (this->pipeline) { this->pipeline->release(); } this->pipeline = pipeline; if (pipeline) { initializePipeline(); if (!globalDescriptorHeap || globalDescriptorHeap->zPipeline() != pipeline) { if (globalDescriptorHeap) { globalDescriptorHeap->release(); } globalDescriptorHeap = pipeline->createGlobalDescriptorHeap(); initializeGlobalDescriptorHeap(); } } } bool DirectX12::isAvailable() { HINSTANCE dxgiDLL = getDLLRegister()->loadDLL("dxgi.dll", "dxgi.dll"); if (!dxgiDLL) return 0; HINSTANCE d3d12DLL = getDLLRegister()->loadDLL("d3d12.dll", "d3d12.dll"); if (!d3d12DLL) { getDLLRegister()->releaseDLL("dxgi.dll"); return 0; } CreateDXGIFactory2Function createFactory = (CreateDXGIFactory2Function)GetProcAddress( dxgiDLL, "CreateDXGIFactory2"); if (!createFactory) { getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d12.dll"); return 0; } D3D12CreateDeviceFunction createDevice = (D3D12CreateDeviceFunction)GetProcAddress( d3d12DLL, "D3D12CreateDevice"); if (!createDevice) { getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d12.dll"); return 0; } #ifdef _DEBUG D3D12GetDebugInterfaceFunction getDebugInterface = (D3D12GetDebugInterfaceFunction)GetProcAddress( d3d12DLL, "D3D12GetDebugInterface"); ID3D12Debug* debug = 0; getDebugInterface(__uuidof(ID3D12Debug), (void**)&debug); debug->EnableDebugLayer(); #endif IDXGIFactory4* factory; UINT createFactoryFlags = 0; #ifdef _DEBUG createFactoryFlags = DXGI_CREATE_FACTORY_DEBUG; #endif HRESULT res = createFactory( createFactoryFlags, __uuidof(IDXGIFactory4), (void**)&factory); if (FAILED(res)) { getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d12.dll"); return 0; } int index = 0; do { IDXGIAdapter1* current; res = factory->EnumAdapters1(index++, ¤t); if (res == S_OK) { DXGI_ADAPTER_DESC1 dxgiAdapterDesc1; current->GetDesc1(&dxgiAdapterDesc1); ID3D12Device5* device = 0; if ((dxgiAdapterDesc1.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) == 0 && SUCCEEDED(createDevice(current, D3D_FEATURE_LEVEL_12_1, __uuidof(ID3D12Device5), (void**)&device))) { device->Release(); current->Release(); factory->Release(); #ifdef _DEBUG debug->Release(); #endif getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d12.dll"); return 1; } current->Release(); } } while (res != DXGI_ERROR_NOT_FOUND); factory->Release(); getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d12.dll"); return 0; } bool Framework::DirectX12::renderGuiBefore3D() const { return true; }