// Load the sample assets. void D3D12Fullscreen::LoadAssets() { // Create an empty root signature. { CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc; rootSignatureDesc.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); ComPtr<ID3DBlob> signature; ComPtr<ID3DBlob> error; ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature))); NAME_D3D12_OBJECT(m_rootSignature); } // Create the pipeline state, which includes compiling and loading shaders. { ComPtr<ID3DBlob> vertexShader; ComPtr<ID3DBlob> pixelShader; ComPtr<ID3DBlob> error; #if defined(_DEBUG) // Enable better shader debugging with the graphics debugging tools. UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; #else UINT compileFlags = 0; #endif ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"shaders.hlsl").c_str(), nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &vertexShader, &error)); ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"shaders.hlsl").c_str(), nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, &pixelShader, &error)); // Define the vertex input layout. D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } }; // Describe and create the graphics pipeline state object (PSO). D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) }; psoDesc.pRootSignature = m_rootSignature.Get(); psoDesc.VS = CD3DX12_SHADER_BYTECODE(vertexShader.Get()); psoDesc.PS = CD3DX12_SHADER_BYTECODE(pixelShader.Get()); psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); psoDesc.DepthStencilState.DepthEnable = FALSE; psoDesc.DepthStencilState.StencilEnable = FALSE; psoDesc.SampleMask = UINT_MAX; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; psoDesc.NumRenderTargets = 1; psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; psoDesc.SampleDesc.Count = 1; ThrowIfFailed(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState))); NAME_D3D12_OBJECT(m_pipelineState); } // Create the command list. ThrowIfFailed(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get(), IID_PPV_ARGS(&m_commandList))); NAME_D3D12_OBJECT(m_commandList); LoadSizeDependentResources(); // Close the command list and execute it to begin the vertex buffer copy into // the default heap. ThrowIfFailed(m_commandList->Close()); ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() }; m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); // Create synchronization objects and wait until assets have been uploaded to the GPU. { ThrowIfFailed(m_device->CreateFence(m_fenceValues[m_frameIndex], D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence))); m_fenceValues[m_frameIndex]++; // Create an event handle to use for frame synchronization. m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); if (m_fenceEvent == nullptr) { ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); } // Wait for the command list to execute; we are reusing the same command // list in our main loop but for now, we just want to wait for setup to // complete before continuing. WaitForGpu(); } }
// Load the rendering pipeline dependencies. void D3D12PredicationQueries::LoadPipeline() { #if defined(_DEBUG) // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } else { ComPtr<IDXGIAdapter1> hardwareAdapter; GetHardwareAdapter(factory.Get(), &hardwareAdapter); ThrowIfFailed(D3D12CreateDevice( hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); NAME_D3D12_OBJECT(m_commandQueue); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.Width = m_width; swapChainDesc.Height = m_height; swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.SampleDesc.Count = 1; ComPtr<IDXGISwapChain1> swapChain; ThrowIfFailed(factory->CreateSwapChainForCoreWindow( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. reinterpret_cast<IUnknown*>(Windows::UI::Core::CoreWindow::GetForCurrentThread()), &swapChainDesc, nullptr, &swapChain )); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); // Describe and create a depth stencil view (DSV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {}; dsvHeapDesc.NumDescriptors = 1; dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&m_dsvHeap))); // Describe and create a constant buffer view (CBV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC cbvHeapDesc = {}; cbvHeapDesc.NumDescriptors = CbvCountPerFrame * FrameCount; cbvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; cbvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&cbvHeapDesc, IID_PPV_ARGS(&m_cbvHeap))); NAME_D3D12_OBJECT(m_cbvHeap); // Describe and create a heap for occlusion queries. D3D12_QUERY_HEAP_DESC queryHeapDesc = {}; queryHeapDesc.Count = 1; queryHeapDesc.Type = D3D12_QUERY_HEAP_TYPE_OCCLUSION; ThrowIfFailed(m_device->CreateQueryHeap(&queryHeapDesc, IID_PPV_ARGS(&m_queryHeap))); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); m_cbvSrvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } // Create frame resources. { CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart()); // Create a RTV and a command allocator for each frame. for (UINT n = 0; n < FrameCount; n++) { ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n]))); m_device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle); rtvHandle.Offset(1, m_rtvDescriptorSize); NAME_D3D12_OBJECT_INDEXED(m_renderTargets, n); ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocators[n]))); } } }
/// <summary> /// Get image .NET runtime version /// </summary> /// <returns>runtime version, "n/a" if nothing found</returns> std::wstring ImageNET::GetImageRuntimeVer( const wchar_t* ImagePath ) { std::wstring LatestVersion = L"n/a"; CComPtr<ICLRMetaHost> MetaHost; // Check if .NET 4 or higher is present auto clrCreate = reinterpret_cast<fnCLRCreateInstancen>( GetProcAddress( LoadLibraryW( L"mscoree.dll" ), "CLRCreateInstance" )); // Legacy runtime. Get exact required version if(!clrCreate) { wchar_t ver[64] = { 0 }; DWORD bytes = 0; auto clrGetVer = reinterpret_cast<fnGetRequestedRuntimeVersion>( GetProcAddress( GetModuleHandleW( L"mscoree.dll" ), "GetRequestedRuntimeVersion" )); clrGetVer( const_cast<LPWSTR>(ImagePath), ver, 64, &bytes ); FreeLibrary( GetModuleHandleW( L"mscoree.dll" ) ); return ver; } // Get highest available else { if (FAILED( clrCreate( CLSID_CLRMetaHost, IID_ICLRMetaHost, reinterpret_cast<LPVOID*>(&MetaHost) ) )) return LatestVersion; CComPtr<IEnumUnknown> Runtimes; if (FAILED( MetaHost->EnumerateInstalledRuntimes( &Runtimes ) )) return LatestVersion; CComPtr<IUnknown> Runtime; CComPtr<ICLRRuntimeInfo> Latest; while (Runtimes->Next( 1, &Runtime, NULL ) == S_OK) { CComPtr<ICLRRuntimeInfo> Current; wchar_t tmpString[MAX_PATH]; DWORD tmp = MAX_PATH * sizeof(wchar_t); if (SUCCEEDED( Runtime->QueryInterface( IID_PPV_ARGS( &Current ) ) )) { if (!Latest) { if (SUCCEEDED( Current->QueryInterface( IID_PPV_ARGS( &Latest ) ) )) { Latest->GetVersionString( tmpString, &tmp ); LatestVersion = tmpString; } } else { if (SUCCEEDED( Current->GetVersionString( tmpString, &tmp ) )) { std::wstring CurrentVersion = tmpString; if (CurrentVersion.compare( LatestVersion ) > 0) { LatestVersion = CurrentVersion; Latest.Release(); Current->QueryInterface( IID_PPV_ARGS( &Latest ) ); } } } } Runtime.Release(); } return LatestVersion; } }
// Writes a set of properties for all objects. void WriteContentPropertiesBulk( IPortableDevice* pDevice) { if (pDevice == NULL) { printf("! A NULL IPortableDevice interface pointer was received\n"); return; } HRESULT hr = S_OK; GUID guidContext = GUID_NULL; CSetBulkValuesCallback* pCallback = NULL; CComPtr<IPortableDeviceProperties> pProperties; CComPtr<IPortableDevicePropertiesBulk> pPropertiesBulk; CComPtr<IPortableDeviceValues> pObjectProperties; CComPtr<IPortableDeviceContent> pContent; CComPtr<IPortableDeviceValuesCollection> pPropertiesToWrite; CComPtr<IPortableDevicePropVariantCollection> pObjectIDs; DWORD cObjectIDs = 0; // 1) Get an IPortableDeviceContent interface from the IPortableDevice interface to // access the content-specific methods. hr = pDevice->Content(&pContent); if (FAILED(hr)) { printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr); } // 2) Get an IPortableDeviceProperties interface from the IPortableDeviceContent interface // to access the property-specific methods. if (SUCCEEDED(hr)) { hr = pContent->Properties(&pProperties); if (FAILED(hr)) { printf("! Failed to get IPortableDeviceProperties from IPortableDevice, hr = 0x%lx\n",hr); } } // 3) Check to see if the driver supports BULK property operations by call QueryInterface // on the IPortableDeviceProperties interface for IPortableDevicePropertiesBulk if (SUCCEEDED(hr)) { hr = pProperties->QueryInterface(IID_PPV_ARGS(&pPropertiesBulk)); if (FAILED(hr)) { printf("This driver does not support BULK property operations.\n"); } } // 4) CoCreate an IPortableDeviceValuesCollection interface to hold the the properties // we wish to write. if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_PortableDeviceValuesCollection, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pPropertiesToWrite)); if (FAILED(hr)) { printf("! Failed to CoCreate IPortableDeviceValuesCollection for bulk property values, hr = 0x%lx\n", hr); } } // 6) Create an instance of the IPortableDevicePropertiesBulkCallback object. if (SUCCEEDED(hr)) { pCallback = new (std::nothrow) CSetBulkValuesCallback(); if (pCallback == NULL) { hr = E_OUTOFMEMORY; printf("! Failed to allocate CSetBulkValuesCallback, hr = 0x%lx\n", hr); } } // 7) Call our helper function CreateIPortableDevicePropVariantCollectionWithAllObjectIDs // to enumerate and create an IPortableDevicePropVariantCollection with the object // identifiers needed to perform the bulk operation on. if (SUCCEEDED(hr)) { hr = CreateIPortableDevicePropVariantCollectionWithAllObjectIDs(pContent, &pObjectIDs); } if (SUCCEEDED(hr)) { hr = pObjectIDs->GetCount(&cObjectIDs); if (FAILED(hr)) { printf("! Failed to get number of objectIDs from IPortableDevicePropVariantCollection, hr = 0x%lx\n", hr); } } // 8) Iterate through object list and add appropriate IPortableDeviceValues to collection if (SUCCEEDED(hr)) { for(DWORD dwIndex = 0; (dwIndex < cObjectIDs) && (hr == S_OK); dwIndex++) { CComPtr<IPortableDeviceValues> pValues; PROPVARIANT pv = {0}; PropVariantInit(&pv); hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pValues)); if (FAILED(hr)) { printf("! Failed to CoCreate CLSID_PortableDeviceValues, hr = 0x%lx\n", hr); } // Get the Object ID whose properties we will set if (hr == S_OK) { hr = pObjectIDs->GetAt(dwIndex, &pv); if (FAILED(hr)) { printf("! Failed to get next Object ID from list, hr = 0x%lx\n", hr); } } // Save them into the IPortableDeviceValues so the driver knows which object this proeprty set belongs to if (hr == S_OK) { hr = pValues->SetStringValue(WPD_OBJECT_ID, pv.pwszVal); if (FAILED(hr)) { printf("! Failed to set WPD_OBJECT_ID, hr = 0x%lx\n", hr); } } // Set the new values. In this sample, we attempt to set the name property. if (hr == S_OK) { CAtlStringW strValue; strValue.Format(L"NewName%d", dwIndex); hr = pValues->SetStringValue(WPD_OBJECT_NAME, strValue.GetString()); if (FAILED(hr)) { printf("! Failed to set WPD_OBJECT_NAME, hr = 0x%lx\n", hr); } } // Add this property set to the collection if (hr == S_OK) { hr = pPropertiesToWrite->Add(pValues); if (FAILED(hr)) { printf("! Failed to add values to collection, hr = 0x%lx\n", hr); } } PropVariantClear(&pv); } } // 9) Call QueueSetValuesByObjectList to initialize the Asynchronous // property operation. if (SUCCEEDED(hr)) { hr = pPropertiesBulk->QueueSetValuesByObjectList(pPropertiesToWrite, pCallback, &guidContext); // 10) Call Start() to actually being the property operation if(SUCCEEDED(hr)) { // Cleanup any previously created global event handles. if (g_hBulkPropertyOperationEvent != NULL) { CloseHandle(g_hBulkPropertyOperationEvent); g_hBulkPropertyOperationEvent = NULL; } // In order to create a simpler to follow example we create and wait infinitly // for the bulk property operation to complete and ignore any errors. // Production code should be written in a more robust manner. // Create the global event handle to wait on for the bulk operation // to complete. g_hBulkPropertyOperationEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (g_hBulkPropertyOperationEvent != NULL) { // Call Start() to actually being the Asynchronous bulk operation. hr = pPropertiesBulk->Start(guidContext); if(FAILED(hr)) { printf("! Failed to start property operation, hr = 0x%lx\n", hr); } } else { printf("! Failed to create the global event handle to wait on for the bulk operation. Aborting operation.\n"); } } else { printf("! QueueSetValuesByObjectList Failed, hr = 0x%lx\n", hr); } } // In order to create a simpler to follow example we will wait infinitly for the operation // to complete and ignore any errors. Production code should be written in a more // robust manner. if (SUCCEEDED(hr)) { if (g_hBulkPropertyOperationEvent != NULL) { WaitForSingleObject(g_hBulkPropertyOperationEvent, INFINITE); } } if (pCallback != NULL) { pCallback->Release(); pCallback = NULL; } // Cleanup any created global event handles before exiting.. if (g_hBulkPropertyOperationEvent != NULL) { CloseHandle(g_hBulkPropertyOperationEvent); g_hBulkPropertyOperationEvent = NULL; } }
/// <summary> /// Called when an asynchronous operation is completed. /// </summary> /// <param name="pAsyncResult">Pointer to the IMFAsyncResult interface. Pass this pointer to the asynchronous End... method to complete the asynchronous call.</param> /// <returns>The result of the operation.</returns> HRESULT ReadByteAsyncCallback::Invoke(IMFAsyncResult* pAsyncResult) { // Enter critical section. EnterCriticalSection(&_critsec); HRESULT hr = S_OK; ULONG pcbRead; IUnknown *pState = NULL; IUnknown *pUnk = NULL; IMFAsyncResult *pCallerResult = NULL; ReadByteContainer *pReader = NULL; // Get the asynchronous result object for the application callback. hr = pAsyncResult->GetState(&pState); if (FAILED(hr)) { goto done; } // Get the caller result interface. hr = pState->QueryInterface(IID_PPV_ARGS(&pCallerResult)); if (FAILED(hr)) { goto done; } // Get the object that holds the state information for the asynchronous method. hr = pCallerResult->GetObject(&pUnk); if (FAILED(hr)) { goto done; } // Get the reader byte container. pReader = static_cast<ReadByteContainer*>(pUnk); // Write the bytes. _byteStream->Read(pReader->_pb, pReader->_cb, &pcbRead); // Assign the number of bytes writen. pReader->_pcbRead = pcbRead; done: // Set the result. // Signal the application. if (pCallerResult) { pCallerResult->SetStatus(hr); MFInvokeCallback(pCallerResult); } // Clean-up. SafeRelease(&pState); SafeRelease(&pUnk); SafeRelease(&pCallerResult); // Leave critical section. LeaveCriticalSection(&_critsec); // Return the result. return hr; }
void DirectShowMetaDataControl::updateMetadata(IFilterGraph2 *graph, IBaseFilter *source, const QString &fileSrc) { m_metadata.clear(); #ifndef QT_NO_SHELLITEM if (!sHCreateItemFromParsingName) { QSystemLibrary lib(QStringLiteral("shell32")); sHCreateItemFromParsingName = (q_SHCreateItemFromParsingName)(lib.resolve("SHCreateItemFromParsingName")); } if (!fileSrc.isEmpty() && sHCreateItemFromParsingName) { IShellItem2* shellItem = 0; if (sHCreateItemFromParsingName(reinterpret_cast<const WCHAR*>(fileSrc.utf16()), 0, IID_PPV_ARGS(&shellItem)) == S_OK) { IPropertyStore *pStore = 0; if (shellItem->GetPropertyStore(GPS_DEFAULT, IID_PPV_ARGS(&pStore)) == S_OK) { DWORD cProps; if (SUCCEEDED(pStore->GetCount(&cProps))) { for (DWORD i = 0; i < cProps; ++i) { PROPERTYKEY key; PROPVARIANT var; PropVariantInit(&var); if (FAILED(pStore->GetAt(i, &key))) continue; if (FAILED(pStore->GetValue(key, &var))) continue; if (IsEqualPropertyKey(key, PKEY_Author)) { m_metadata.insert(QMediaMetaData::Author, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Title)) { m_metadata.insert(QMediaMetaData::Title, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_SubTitle)) { m_metadata.insert(QMediaMetaData::SubTitle, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_ParentalRating)) { m_metadata.insert(QMediaMetaData::ParentalRating, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Comment)) { m_metadata.insert(QMediaMetaData::Description, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Copyright)) { m_metadata.insert(QMediaMetaData::Copyright, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_ProviderStyle)) { m_metadata.insert(QMediaMetaData::Genre, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_Year)) { m_metadata.insert(QMediaMetaData::Year, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_DateEncoded)) { m_metadata.insert(QMediaMetaData::Date, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Rating)) { m_metadata.insert(QMediaMetaData::UserRating, int((convertValue(var).toUInt() - 1) / qreal(98) * 100)); } else if (IsEqualPropertyKey(key, PKEY_Keywords)) { m_metadata.insert(QMediaMetaData::Keywords, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Language)) { m_metadata.insert(QMediaMetaData::Language, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_Publisher)) { m_metadata.insert(QMediaMetaData::Publisher, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_Duration)) { m_metadata.insert(QMediaMetaData::Duration, (convertValue(var).toLongLong() + 10000) / 10000); } else if (IsEqualPropertyKey(key, PKEY_Audio_EncodingBitrate)) { m_metadata.insert(QMediaMetaData::AudioBitRate, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_AverageLevel)) { m_metadata.insert(QMediaMetaData::AverageLevel, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Audio_ChannelCount)) { m_metadata.insert(QMediaMetaData::ChannelCount, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Audio_PeakValue)) { m_metadata.insert(QMediaMetaData::PeakValue, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Audio_SampleRate)) { m_metadata.insert(QMediaMetaData::SampleRate, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_AlbumTitle)) { m_metadata.insert(QMediaMetaData::AlbumTitle, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_AlbumArtist)) { m_metadata.insert(QMediaMetaData::AlbumArtist, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Artist)) { m_metadata.insert(QMediaMetaData::ContributingArtist, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Composer)) { m_metadata.insert(QMediaMetaData::Composer, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Conductor)) { m_metadata.insert(QMediaMetaData::Conductor, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Lyrics)) { m_metadata.insert(QMediaMetaData::Lyrics, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Mood)) { m_metadata.insert(QMediaMetaData::Mood, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_TrackNumber)) { m_metadata.insert(QMediaMetaData::TrackNumber, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Genre)) { m_metadata.insert(QMediaMetaData::Genre, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_ThumbnailStream)) { m_metadata.insert(QMediaMetaData::ThumbnailImage, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Video_FrameHeight)) { QSize res; res.setHeight(convertValue(var).toUInt()); if (SUCCEEDED(pStore->GetValue(PKEY_Video_FrameWidth, &var))) res.setWidth(convertValue(var).toUInt()); m_metadata.insert(QMediaMetaData::Resolution, res); } else if (IsEqualPropertyKey(key, PKEY_Video_HorizontalAspectRatio)) { QSize aspectRatio; aspectRatio.setWidth(convertValue(var).toUInt()); if (SUCCEEDED(pStore->GetValue(PKEY_Video_VerticalAspectRatio, &var))) aspectRatio.setHeight(convertValue(var).toUInt()); m_metadata.insert(QMediaMetaData::PixelAspectRatio, aspectRatio); } else if (IsEqualPropertyKey(key, PKEY_Video_FrameRate)) { m_metadata.insert(QMediaMetaData::VideoFrameRate, convertValue(var).toReal() / 1000); } else if (IsEqualPropertyKey(key, PKEY_Video_EncodingBitrate)) { m_metadata.insert(QMediaMetaData::VideoBitRate, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Video_Director)) { m_metadata.insert(QMediaMetaData::Director, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_Writer)) { m_metadata.insert(QMediaMetaData::Writer, convertValue(var)); } PropVariantClear(&var); } } pStore->Release(); } shellItem->Release(); } } if (!m_metadata.isEmpty()) goto send_event; #endif #ifndef QT_NO_WMSDK IWMHeaderInfo *info = com_cast<IWMHeaderInfo>(source, IID_IWMHeaderInfo); if (info) { Q_FOREACH (const QWMMetaDataKey &key, *qt_wmMetaDataKeys()) { QVariant var = getValue(info, key.wmName); if (var.isValid()) { if (key.qtName == QMediaMetaData::Duration) { // duration is provided in 100-nanosecond units, convert to milliseconds var = (var.toLongLong() + 10000) / 10000; } else if (key.qtName == QMediaMetaData::Resolution) { QSize res; res.setHeight(var.toUInt()); res.setWidth(getValue(info, L"WM/VideoWidth").toUInt()); var = res; } else if (key.qtName == QMediaMetaData::VideoFrameRate) { var = var.toReal() / 1000.f; } else if (key.qtName == QMediaMetaData::PixelAspectRatio) { QSize aspectRatio; aspectRatio.setWidth(var.toUInt()); aspectRatio.setHeight(getValue(info, L"AspectRatioY").toUInt()); var = aspectRatio; } else if (key.qtName == QMediaMetaData::UserRating) { var = (var.toUInt() - 1) / qreal(98) * 100; } m_metadata.insert(key.qtName, var); } } info->Release(); } if (!m_metadata.isEmpty()) goto send_event; #endif { IAMMediaContent *content = 0; if ((!graph || graph->QueryInterface( IID_IAMMediaContent, reinterpret_cast<void **>(&content)) != S_OK) && (!source || source->QueryInterface( IID_IAMMediaContent, reinterpret_cast<void **>(&content)) != S_OK)) { content = 0; } if (content) { BSTR string = 0; if (content->get_AuthorName(&string) == S_OK) m_metadata.insert(QMediaMetaData::Author, convertBSTR(&string)); if (content->get_Title(&string) == S_OK) m_metadata.insert(QMediaMetaData::Title, convertBSTR(&string)); if (content->get_Description(&string) == S_OK) m_metadata.insert(QMediaMetaData::Description, convertBSTR(&string)); if (content->get_Rating(&string) == S_OK) m_metadata.insert(QMediaMetaData::UserRating, convertBSTR(&string)); if (content->get_Copyright(&string) == S_OK) m_metadata.insert(QMediaMetaData::Copyright, convertBSTR(&string)); content->Release(); } } send_event: // DirectShowMediaPlayerService holds a lock at this point so defer emitting signals to a later // time. QCoreApplication::postEvent(this, new QEvent(QEvent::Type(MetaDataChanged))); }
// Retreives the object identifier for the persistent unique identifer void GetObjectIdentifierFromPersistentUniqueIdentifier( IPortableDevice* pDevice) { if (pDevice == NULL) { printf("! A NULL IPortableDevice interface pointer was received\n"); return; } HRESULT hr = S_OK; WCHAR szSelection[81] = {0}; CComPtr<IPortableDeviceContent> pContent; CComPtr<IPortableDevicePropVariantCollection> pPersistentUniqueIDs; CComPtr<IPortableDevicePropVariantCollection> pObjectIDs; //<SnippetContentProp7> // Prompt user to enter an unique identifier to convert to an object idenifier. printf("Enter the Persistant Unique Identifier of the object you wish to convert into an object identifier.\n>"); hr = StringCbGetsW(szSelection,sizeof(szSelection)); if (FAILED(hr)) { printf("An invalid persistent object identifier was specified, aborting the query operation\n"); } //</SnippetContentProp7> // 1) Get an IPortableDeviceContent interface from the IPortableDevice interface to // access the content-specific methods. //<SnippetContentProp8> if (SUCCEEDED(hr)) { hr = pDevice->Content(&pContent); if (FAILED(hr)) { printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr); } } //</SnippetContentProp8> // 2) CoCreate an IPortableDevicePropVariantCollection interface to hold the the Unique Identifiers // to query for Object Identifiers. // // NOTE: This is a collection interface so more than 1 identifier can be requested at a time. // This sample only requests a single unique identifier. //<SnippetContentProp9> hr = CoCreateInstance(CLSID_PortableDevicePropVariantCollection, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pPersistentUniqueIDs)); //</SnippetContentProp9> //<SnippetContentProp10> if (SUCCEEDED(hr)) { if (pPersistentUniqueIDs != NULL) { PROPVARIANT pv = {0}; PropVariantInit(&pv); // Initialize a PROPVARIANT structure with the object identifier string // that the user selected above. Notice we are allocating memory for the // PWSTR value. This memory will be freed when PropVariantClear() is // called below. pv.vt = VT_LPWSTR; pv.pwszVal = AtlAllocTaskWideString(szSelection); if (pv.pwszVal != NULL) { // Add the object identifier to the objects-to-delete list // (We are only deleting 1 in this example) hr = pPersistentUniqueIDs->Add(&pv); if (SUCCEEDED(hr)) { // 3) Attempt to get the unique idenifier for the object from the device hr = pContent->GetObjectIDsFromPersistentUniqueIDs(pPersistentUniqueIDs, &pObjectIDs); if (SUCCEEDED(hr)) { PROPVARIANT pvId = {0}; hr = pObjectIDs->GetAt(0, &pvId); if (SUCCEEDED(hr)) { printf("The persistent unique identifier '%ws' relates to object identifier '%ws' on the device.\n", szSelection, pvId.pwszVal); } else { printf("! Failed to get the object identifier for '%ws' from the IPortableDevicePropVariantCollection, hr = 0x%lx\n",szSelection, hr); } // Free the returned allocated string from the GetAt() call PropVariantClear(&pvId); } else { printf("! Failed to get the object identifier from persistent object idenifier '%ws', hr = 0x%lx\n",szSelection, hr); } } else { printf("! Failed to get the object identifier from persistent object idenifier because we could no add the persistent object identifier string to the IPortableDevicePropVariantCollection, hr = 0x%lx\n",hr); } } else { hr = E_OUTOFMEMORY; printf("! Failed to get the object identifier because we could no allocate memory for the persistent object identifier string, hr = 0x%lx\n",hr); } // Free any allocated values in the PROPVARIANT before exiting PropVariantClear(&pv); } } //</SnippetContentProp10> }
CSaveThumbnailsDialog::CSaveThumbnailsDialog( int rows, int cols, int width, int quality, int levelPNG, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, LPCTSTR lpszFilter, CWnd* pParentWnd) : CFileDialog(FALSE, lpszDefExt, lpszFileName, OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR, lpszFilter, pParentWnd) , m_rows(rows) , m_cols(cols) , m_width(width) , m_quality(quality) , m_levelPNG(levelPNG) { if (IsWinVistaOrLater()) { IFileDialogCustomize* pfdc = GetIFileDialogCustomize(); if (pfdc) { // Create an event handling object, and hook it up to the dialog. IFileDialogEvents *pfde = NULL; HRESULT hr = _CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde)); if (SUCCEEDED(hr)) { // Hook up the event handler. DWORD dwCookie; hr = GetIFileSaveDialog()->Advise(pfde, &dwCookie); if (SUCCEEDED(hr)) { ; } } CString str; pfdc->StartVisualGroup(IDS_THUMB_THUMBNAILS, ResStr(IDS_THUMB_THUMBNAILS)); pfdc->AddText(IDS_THUMB_ROWNUMBER, ResStr(IDS_THUMB_ROWNUMBER)); str.Format(L"%d", max(1, min(20, m_rows))); pfdc->AddEditBox(IDC_EDIT1, str); pfdc->AddText(IDS_THUMB_COLNUMBER, ResStr(IDS_THUMB_COLNUMBER)); str.Format(L"%d", max(1, min(10, m_cols))); pfdc->AddEditBox(IDC_EDIT2, str); pfdc->EndVisualGroup(); pfdc->StartVisualGroup(IDS_THUMB_IMAGE_WIDTH, ResStr(IDS_THUMB_IMAGE_WIDTH)); pfdc->AddText(IDS_THUMB_PIXELS, ResStr(IDS_THUMB_PIXELS)); str.Format(L"%d", max(256, min(2560, m_width))); pfdc->AddEditBox(IDC_EDIT3, str); pfdc->EndVisualGroup(); pfdc->StartVisualGroup(IDS_THUMB_IMAGE_QUALITY, ResStr(IDS_THUMB_IMAGE_QUALITY)); pfdc->AddText(IDS_THUMB_QUALITY, ResStr(IDS_THUMB_QUALITY)); str.Format(L"%d", max(70, min(100, m_quality))); pfdc->AddEditBox(IDC_EDIT4, str); pfdc->AddText(IDS_THUMB_LEVEL, ResStr(IDS_THUMB_LEVEL)); str.Format(L"%d", max(1, min(9, m_levelPNG))); pfdc->AddEditBox(IDC_EDIT5, str); pfdc->EndVisualGroup(); pfdc->Release(); } } else { SetTemplate(0, IDD_SAVETHUMBSDIALOGTEMPL); } }
bool ResourceManager::LoadFile(ID2D1HwndRenderTarget* renderTarget, wchar_t * filename) { HRESULT result; IWICImagingFactory2* wicFactory; IWICBitmapDecoder* wicDecoder; IWICBitmapFrameDecode* wicFrame; IWICBitmapFlipRotator* wicFlip; IWICFormatConverter *wicConverter; Sprite* newSprite; // WIC의 각종 인터페이스를 사용하기 위한 factory 생성 result = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&wicFactory)); if (FAILED(result)) return false; // 파일을 읽고 디코딩 하기 위한 decoder 생성 result = wicFactory->CreateDecoderFromFilename(filename, nullptr, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &wicDecoder); if (FAILED(result)) return false; // decoder에서 프레임을 얻어옴, // 일반적인 이미지 파일은 single frame만을 지원하므로 0으로 고정 result = wicDecoder->GetFrame(0, &wicFrame); if (FAILED(result)) return false; // 수평으로 뒤집힌 이미지를 얻기 위해 BitmapFlipRotator 생성 result = wicFactory->CreateBitmapFlipRotator(&wicFlip); if (FAILED(result)) return false; // wicFrame를 수평으로 뒤집음 wicFlip->Initialize(wicFrame, WICBitmapTransformFlipHorizontal); // WICBitmap을 D2DBitmap으로 변환시키기 위해 format converter 생성 result = wicFactory->CreateFormatConverter(&wicConverter); if (FAILED(result)) return false; // Converter[0]의 Format을 일반 이미지(wicFrame)에 맞춤 result = wicConverter->Initialize(wicFrame, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.0f, WICBitmapPaletteTypeCustom); if (FAILED(result)) return false; // 리소스 정보를 저장 할 Sprite 생성 newSprite = new Sprite(renderTarget); if (!newSprite) return false; // WICBitmap을 D2DBitmap으로 변환 //result = renderTarget->CreateBitmapFromWicBitmap(wicConverter, nullptr, &m_Bitmap); result = renderTarget->CreateBitmapFromWicBitmap(wicConverter, nullptr, newSprite->GetBitmap()); if (FAILED(result)) return false; ID2D1Bitmap* bitmap = *(newSprite->GetBitmap()); int numberOfFrame = bitmap->GetSize().width / IMAGE_SIZE; int numberOfAction = bitmap->GetSize().height / IMAGE_SIZE; newSprite->Initialize(numberOfFrame, numberOfAction); wchar_t* buffer = new wchar_t[128]; wcscpy_s(buffer, wcslen(filename) + 1, filename); // 스프라이트 등록 m_Sprites.push_back(newSprite); m_Filenames.push_back(buffer); wicConverter->Release(); wicConverter = nullptr; wicFrame->Release(); wicFrame = nullptr; wicFlip->Release(); wicFlip = nullptr; wicDecoder->Release(); wicDecoder = nullptr; wicFactory->Release(); wicFactory = nullptr; return true; }
// Load the rendering pipeline dependencies. void D3D1211on12::LoadPipeline() { UINT d3d11DeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; D2D1_FACTORY_OPTIONS d2dFactoryOptions = {}; #ifdef _DEBUG // Enable the D2D debug layer. d2dFactoryOptions.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; // Enable the D3D11 debug layer. d3d11DeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_d3d12Device) )); } else { ThrowIfFailed(D3D12CreateDevice( nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_d3d12Device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_d3d12Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); // Describe the swap chain. DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.BufferDesc.Width = m_width; swapChainDesc.BufferDesc.Height = m_height; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.OutputWindow = m_hwnd; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.Windowed = TRUE; ComPtr<IDXGISwapChain> swapChain; ThrowIfFailed(factory->CreateSwapChain( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. &swapChainDesc, &swapChain )); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create an 11 device wrapped around the 12 device and share // 12's command queue. ComPtr<ID3D11Device> d3d11Device; ThrowIfFailed(D3D11On12CreateDevice( m_d3d12Device.Get(), d3d11DeviceFlags, nullptr, 0, reinterpret_cast<IUnknown**>(m_commandQueue.GetAddressOf()), 1, 0, &d3d11Device, &m_d3d11DeviceContext, nullptr )); // Query the 11On12 device from the 11 device. ThrowIfFailed(d3d11Device.As(&m_d3d11On12Device)); // Create D2D/DWrite components. { D2D1_DEVICE_CONTEXT_OPTIONS deviceOptions = D2D1_DEVICE_CONTEXT_OPTIONS_NONE; ThrowIfFailed(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory3), &d2dFactoryOptions, &m_d2dFactory)); ComPtr<IDXGIDevice> dxgiDevice; ThrowIfFailed(m_d3d11On12Device.As(&dxgiDevice)); ThrowIfFailed(m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice)); ThrowIfFailed(m_d2dDevice->CreateDeviceContext(deviceOptions, &m_d2dDeviceContext)); ThrowIfFailed(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &m_dWriteFactory)); } // Query the desktop's dpi settings, which will be used to create // D2D's render targets. float dpiX; float dpiY; m_d2dFactory->GetDesktopDpi(&dpiX, &dpiY); D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1( D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED), dpiX, dpiY ); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_d3d12Device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); m_rtvDescriptorSize = m_d3d12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); } // Create frame resources. { CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart()); // Create a RTV, D2D render target, and a command allocator for each frame. for (UINT n = 0; n < FrameCount; n++) { ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n]))); m_d3d12Device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle); // Create a wrapped 11On12 resource of this back buffer. Since we are // rendering all D3D12 content first and then all D2D content, we specify // the In resource state as RENDER_TARGET - because D3D12 will have last // used it in this state - and the Out resource state as PRESENT. When // ReleaseWrappedResources() is called on the 11On12 device, the resource // will be transitioned to the PRESENT state. D3D11_RESOURCE_FLAGS d3d11Flags = { D3D11_BIND_RENDER_TARGET }; ThrowIfFailed(m_d3d11On12Device->CreateWrappedResource( m_renderTargets[n].Get(), &d3d11Flags, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT, IID_PPV_ARGS(&m_wrappedBackBuffers[n]) )); // Create a render target for D2D to draw directly to this back buffer. ComPtr<IDXGISurface> surface; ThrowIfFailed(m_wrappedBackBuffers[n].As(&surface)); ThrowIfFailed(m_d2dDeviceContext->CreateBitmapFromDxgiSurface( surface.Get(), &bitmapProperties, &m_d2dRenderTargets[n] )); rtvHandle.Offset(1, m_rtvDescriptorSize); ThrowIfFailed(m_d3d12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocators[n]))); } } }
HBITMAP CGene::DecodePicture(CString filePath) { HRESULT hr; HBITMAP bitmapHandle = NULL; #if WIC if (bitmapHandle == NULL) { // Windows Imaging Component and Direct2D Image Viewer Win32 Sample\C++\WicViewerD2D.cpp CComPtr<IWICImagingFactory> pWICFactory; hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pWICFactory) ); if (SUCCEEDED(hr)) { CComPtr<IWICBitmapDecoder> pDecoder; hr = pWICFactory->CreateDecoderFromFilename( filePath, NULL, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &pDecoder ); if (SUCCEEDED(hr)) { CComPtr<IWICBitmapFrameDecode> pFrame; hr = pDecoder->GetFrame(0, &pFrame); if (SUCCEEDED(hr)) { CComPtr<IWICFormatConverter> pConvertedSourceBitmap; hr = pWICFactory->CreateFormatConverter(&pConvertedSourceBitmap); if (SUCCEEDED(hr)) { hr = pConvertedSourceBitmap->Initialize( pFrame, GUID_WICPixelFormat32bppBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeCustom ); if (SUCCEEDED(hr)) { UINT cx = 0, cy = 0; hr = pConvertedSourceBitmap->GetSize(&cx, &cy); if (SUCCEEDED(hr)) { struct CompatibleDCHandle { HDC hMemDC; CompatibleDCHandle(): hMemDC(CreateCompatibleDC(NULL)) { } ~CompatibleDCHandle() { if (hMemDC != NULL) { DeleteDC(hMemDC); } } }; CompatibleDCHandle compatDC; BITMAPINFO bi = { sizeof(BITMAPINFOHEADER), (LONG)cx, -(LONG)cy, 1, 32, BI_RGB, 4 * cx * cy }; struct DIBSectionHandle { HBITMAP bitmapHandle; void *pvBits; DIBSectionHandle(CompatibleDCHandle &compatDC, BITMAPINFO &bi) { bitmapHandle = CreateDIBSection( compatDC.hMemDC, &bi, DIB_RGB_COLORS, &pvBits, NULL, 0 ); } ~DIBSectionHandle() { if (bitmapHandle != NULL) { DeleteObject(bitmapHandle); } } HBITMAP Detach() { HBITMAP hbm = bitmapHandle; bitmapHandle = NULL; return hbm; } bool Has() const { return bitmapHandle != NULL; } }; DIBSectionHandle bitmap(compatDC, bi); if (bitmap.Has()) { WICRect bitmapRect = {0, 0, cx, cy}; hr = pConvertedSourceBitmap->CopyPixels( &bitmapRect, 4 * cx, bi.bmiHeader.biSizeImage, reinterpret_cast<PBYTE>(bitmap.pvBits) ); if (SUCCEEDED(hr)) { bitmapHandle = bitmap.Detach(); } } } } } } } } } #endif #if 1 // GDI_LOADIMAGE if (bitmapHandle == NULL) { bitmapHandle = reinterpret_cast<HBITMAP>(LoadImage(NULL, filePath, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE|LR_VGACOLOR)); } #endif return bitmapHandle; }
// Load the sample assets. void D3D1211on12::LoadAssets() { // Create an empty root signature. { CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc; rootSignatureDesc.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); ComPtr<ID3DBlob> signature; ComPtr<ID3DBlob> error; ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); ThrowIfFailed(m_d3d12Device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature))); } // Create the pipeline state, which includes compiling and loading shaders. { ComPtr<ID3DBlob> vertexShader; ComPtr<ID3DBlob> pixelShader; #ifdef _DEBUG // Enable better shader debugging with the graphics debugging tools. UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; #else UINT compileFlags = 0; #endif ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"shaders.hlsl").c_str(), nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &vertexShader, nullptr)); ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"shaders.hlsl").c_str(), nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, &pixelShader, nullptr)); // Define the vertex input layout. D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } }; // Describe and create the graphics pipeline state object (PSO). D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) }; psoDesc.pRootSignature = m_rootSignature.Get(); psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()), vertexShader->GetBufferSize() }; psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()), pixelShader->GetBufferSize() }; psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); psoDesc.DepthStencilState.DepthEnable = FALSE; psoDesc.DepthStencilState.StencilEnable = FALSE; psoDesc.SampleMask = UINT_MAX; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; psoDesc.NumRenderTargets = 1; psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; psoDesc.SampleDesc.Count = 1; ThrowIfFailed(m_d3d12Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState))); } ThrowIfFailed(m_d3d12Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get(), IID_PPV_ARGS(&m_commandList))); // Create D2D/DWrite objects for rendering text. { ThrowIfFailed(m_d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &m_textBrush)); ThrowIfFailed(m_dWriteFactory->CreateTextFormat( L"Verdana", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 50, L"en-us", &m_textFormat )); ThrowIfFailed(m_textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER)); ThrowIfFailed(m_textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER)); } ComPtr<ID3D12Resource> vertexBufferUpload; // Create the vertex buffer. { // Define the geometry for a triangle. Vertex triangleVertices[] = { { { 0.0f, 0.25f * m_aspectRatio, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, { { 0.25f, -0.25f * m_aspectRatio, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, { { -0.25f, -0.25f * m_aspectRatio, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } } }; const UINT vertexBufferSize = sizeof(triangleVertices); ThrowIfFailed(m_d3d12Device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize), D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&m_vertexBuffer))); ThrowIfFailed(m_d3d12Device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&vertexBufferUpload))); // Copy data to the intermediate upload heap and then schedule a copy // from the upload heap to the vertex buffer. D3D12_SUBRESOURCE_DATA vertexData = {}; vertexData.pData = reinterpret_cast<UINT8*>(triangleVertices); vertexData.RowPitch = vertexBufferSize; vertexData.SlicePitch = vertexData.RowPitch; UpdateSubresources<1>(m_commandList.Get(), m_vertexBuffer.Get(), vertexBufferUpload.Get(), 0, 0, 1, &vertexData); m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_vertexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER)); // Initialize the vertex buffer view. m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress(); m_vertexBufferView.StrideInBytes = sizeof(Vertex); m_vertexBufferView.SizeInBytes = vertexBufferSize; } // Close the command list and execute it to begin the vertex buffer copy into // the default heap. ThrowIfFailed(m_commandList->Close()); ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() }; m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); // Create synchronization objects and wait until assets have been uploaded to the GPU. { ThrowIfFailed(m_d3d12Device->CreateFence(m_fenceValues[m_frameIndex], D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(m_fence.GetAddressOf()))); m_fenceValues[m_frameIndex]++; // Create an event handle to use for frame synchronization. m_fenceEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS); if (m_fenceEvent == nullptr) { ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); } // Wait for the command list to execute; we are reusing the same command // list in our main loop but for now, we just want to wait for setup to // complete before continuing. WaitForGpu(); } }
// Load the rendering pipeline dependencies. void D3D12Fullscreen::LoadPipeline() { #if defined(_DEBUG) // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } else { ComPtr<IDXGIAdapter1> hardwareAdapter; GetHardwareAdapter(factory.Get(), &hardwareAdapter); ThrowIfFailed(D3D12CreateDevice( hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); NAME_D3D12_OBJECT(m_commandQueue); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.Width = m_width; swapChainDesc.Height = m_height; swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.SampleDesc.Count = 1; ComPtr<IDXGISwapChain1> swapChain; ThrowIfFailed(factory->CreateSwapChainForHwnd( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. Win32Application::GetHwnd(), &swapChainDesc, nullptr, nullptr, &swapChain )); // This sample does not support fullscreen transitions. ThrowIfFailed(factory->MakeWindowAssociation(Win32Application::GetHwnd(), DXGI_MWA_NO_ALT_ENTER)); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); } // Create a command allocator for each frame. for (UINT n = 0; n < FrameCount; n++) { ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocators[n]))); } }
void D3D12Fullscreen::LoadSizeDependentResources() { m_viewport.Width = static_cast<float>(m_width); m_viewport.Height = static_cast<float>(m_height); m_viewport.MaxDepth = 1.0f; m_scissorRect.right = static_cast<LONG>(m_width); m_scissorRect.bottom = static_cast<LONG>(m_height); // Create frame resources. { CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart()); // Create a RTV for each frame. for (UINT n = 0; n < FrameCount; n++) { ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n]))); m_device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle); rtvHandle.Offset(1, m_rtvDescriptorSize); WCHAR name[25]; if (swprintf_s(name, L"m_renderTargets[%u]", n) > 0) { SetName(m_renderTargets[n].Get(), name); } } } // Create/update the vertex buffer. When updating the vertex buffer it is important // to ensure that the GPU is finished using the resource before it is released. // The OnSizeChanged method waits for the GPU to be idle before this method is // called. { // Define the geometry for a triangle that stays the same size regardless // of the window size. This is not the recommended way to transform vertices. // The same effect could be achieved by using constant buffers and // transforming a static set of vertices in the vertex shader, but this // sample merely demonstrates modifying a resource that is tied to the render // target size. // Other apps might also resize intermediate render targets or depth stencils // at this time. float x = TriangleWidth / m_viewport.Width; float y = TriangleWidth / m_viewport.Height; Vertex triangleVertices[] = { { { 0.0f, y, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, { { x, -y, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, { { -x, -y, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } } }; const UINT vertexBufferSize = sizeof(triangleVertices); ThrowIfFailed(m_device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize), D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&m_vertexBuffer))); ThrowIfFailed(m_device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&m_vertexBufferUpload))); NAME_D3D12_OBJECT(m_vertexBuffer); // Copy data to the intermediate upload heap and then schedule a copy // from the upload heap to the vertex buffer. UINT8* pVertexDataBegin; CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. ThrowIfFailed(m_vertexBufferUpload->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin))); memcpy(pVertexDataBegin, triangleVertices, sizeof(triangleVertices)); m_vertexBufferUpload->Unmap(0, nullptr); m_commandList->CopyBufferRegion(m_vertexBuffer.Get(), 0, m_vertexBufferUpload.Get(), 0, vertexBufferSize); m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_vertexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER)); // Initialize the vertex buffer views. m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress(); m_vertexBufferView.StrideInBytes = sizeof(Vertex); m_vertexBufferView.SizeInBytes = vertexBufferSize; } m_resizeResources = false; }
FramebufferManager::FramebufferManager() { m_target_width = std::max(Renderer::GetTargetWidth(), 1); m_target_height = std::max(Renderer::GetTargetHeight(), 1); DXGI_SAMPLE_DESC sample_desc; sample_desc.Count = g_ActiveConfig.iMultisamples; sample_desc.Quality = 0; ID3D12Resource* buf12; D3D12_RESOURCE_DESC texdesc12; D3D12_CLEAR_VALUE optimized_clear_valueRTV = { DXGI_FORMAT_R8G8B8A8_UNORM, { 0.0f, 0.0f, 0.0f, 1.0f } }; D3D12_CLEAR_VALUE optimized_clear_valueDSV = CD3DX12_CLEAR_VALUE(DXGI_FORMAT_D32_FLOAT, 0.0f, 0); HRESULT hr; m_EFBLayers = m_efb.slices = (g_ActiveConfig.iStereoMode > 0) ? 2 : 1; // EFB color texture - primary render target texdesc12 = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, m_target_width, m_target_height, m_efb.slices, 1, sample_desc.Count, sample_desc.Quality, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET); hr = D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COMMON, &optimized_clear_valueRTV, IID_PPV_ARGS(&buf12)); m_efb.color_tex = new D3DTexture2D(buf12, (D3D11_BIND_FLAG)(D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET), DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, (sample_desc.Count > 1), D3D12_RESOURCE_STATE_COMMON); SAFE_RELEASE(buf12); // Temporary EFB color texture - used in ReinterpretPixelData texdesc12 = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, m_target_width, m_target_height, m_efb.slices, 1, sample_desc.Count, sample_desc.Quality, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET); CheckHR(D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COMMON, &optimized_clear_valueRTV, IID_PPV_ARGS(&buf12))); m_efb.color_temp_tex = new D3DTexture2D(buf12, (D3D11_BIND_FLAG)(D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET), DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, (sample_desc.Count > 1), D3D12_RESOURCE_STATE_COMMON); SAFE_RELEASE(buf12); D3D::SetDebugObjectName12(m_efb.color_temp_tex->GetTex12(), "EFB color temp texture"); // AccessEFB - Sysmem buffer used to retrieve the pixel data from color_tex texdesc12 = CD3DX12_RESOURCE_DESC::Buffer(64 * 1024); CheckHR(D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&m_efb.color_staging_buf))); CHECK(hr == S_OK, "create EFB color staging buffer (hr=%#x)", hr); // EFB depth buffer - primary depth buffer texdesc12 = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R32_TYPELESS, m_target_width, m_target_height, m_efb.slices, 1, sample_desc.Count, sample_desc.Quality, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL); CheckHR(D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COMMON, &optimized_clear_valueDSV, IID_PPV_ARGS(&buf12))); m_efb.depth_tex = new D3DTexture2D(buf12, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE), DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_UNKNOWN, (sample_desc.Count > 1), D3D12_RESOURCE_STATE_COMMON); SAFE_RELEASE(buf12); D3D::SetDebugObjectName12(m_efb.depth_tex->GetTex12(), "EFB depth texture"); // Render buffer for AccessEFB (depth data) texdesc12 = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R32_FLOAT, 1, 1, m_efb.slices, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET); optimized_clear_valueRTV.Format = DXGI_FORMAT_R32_FLOAT; hr = D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COMMON, &optimized_clear_valueRTV, IID_PPV_ARGS(&buf12)); CHECK(hr == S_OK, "create EFB depth read texture (hr=%#x)", hr); m_efb.depth_read_texture = new D3DTexture2D(buf12, D3D11_BIND_RENDER_TARGET, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, false, D3D12_RESOURCE_STATE_COMMON); SAFE_RELEASE(buf12); D3D::SetDebugObjectName12(m_efb.depth_read_texture->GetTex12(), "EFB depth read texture (used in Renderer::AccessEFB)"); // AccessEFB - Sysmem buffer used to retrieve the pixel data from depth_read_texture texdesc12 = CD3DX12_RESOURCE_DESC::Buffer(64 * 1024); hr = D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&m_efb.depth_staging_buf)); CHECK(hr == S_OK, "create EFB depth staging buffer (hr=%#x)", hr); D3D::SetDebugObjectName12(m_efb.depth_staging_buf, "EFB depth staging texture (used for Renderer::AccessEFB)"); if (g_ActiveConfig.iMultisamples > 1) { // Framebuffer resolve textures (color+depth) texdesc12 = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, m_target_width, m_target_height, m_efb.slices, 1); hr = D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(&buf12)); CHECK(hr == S_OK, "create EFB color resolve texture (size: %dx%d)", m_target_width, m_target_height); m_efb.resolved_color_tex = new D3DTexture2D(buf12, D3D11_BIND_SHADER_RESOURCE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, false, D3D12_RESOURCE_STATE_COMMON); SAFE_RELEASE(buf12); D3D::SetDebugObjectName12(m_efb.resolved_color_tex->GetTex12(), "EFB color resolve texture shader resource view"); texdesc12 = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R32_TYPELESS, m_target_width, m_target_height, m_efb.slices, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL); hr = D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(&buf12)); CHECK(hr == S_OK, "create EFB depth resolve texture (size: %dx%d; hr=%#x)", m_target_width, m_target_height, hr); m_efb.resolved_depth_tex = new D3DTexture2D(buf12, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE), DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_UNKNOWN, false, D3D12_RESOURCE_STATE_COMMON); SAFE_RELEASE(buf12); D3D::SetDebugObjectName12(m_efb.resolved_depth_tex->GetTex12(), "EFB depth resolve texture shader resource view"); m_depth_resolve_depth_stencil_desc = {}; m_depth_resolve_depth_stencil_desc.StencilEnable = FALSE; m_depth_resolve_depth_stencil_desc.DepthEnable = TRUE; m_depth_resolve_depth_stencil_desc.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; m_depth_resolve_depth_stencil_desc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; } else { m_efb.resolved_color_tex = nullptr; m_efb.resolved_depth_tex = nullptr; } s_xfbEncoder.Init(); }
void dx::initialise() { gDX.viewport.Width = static_cast<float>(platform::ui::width()); gDX.viewport.Height = static_cast<float>(platform::ui::height()); gDX.viewport.MaxDepth = 1.0f; gDX.scissorRect.right = static_cast<LONG>(platform::ui::width()); gDX.scissorRect.bottom = static_cast<LONG>(platform::ui::height()); #ifdef _DEBUG // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); // Always use WARP for now... static const bool USE_WARP_DEVICE = true; if (USE_WARP_DEVICE) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&gDX.device) )); } else { ThrowIfFailed(D3D12CreateDevice( nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&gDX.device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(gDX.device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&gDX.commandQueue))); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = gDX.FrameCount; swapChainDesc.BufferDesc.Width = platform::ui::width(); swapChainDesc.BufferDesc.Height = platform::ui::height(); swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.OutputWindow = (HWND)platform::ui::hwnd(); swapChainDesc.SampleDesc.Count = 1; swapChainDesc.Windowed = TRUE; ComPtr<IDXGISwapChain> swapChain; ThrowIfFailed(factory->CreateSwapChain( gDX.commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. &swapChainDesc, &swapChain )); ThrowIfFailed(swapChain.As(&gDX.swapChain)); gDX.frameIndex = gDX.swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = gDX.FrameCount + 128; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; gDX.rtvHeap = new DXHeap(gDX.device.Get(), rtvHeapDesc); // Describe and create a depth stencil view (DSV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {}; dsvHeapDesc.NumDescriptors = 128; dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; gDX.dsvHeap = new DXHeap(gDX.device.Get(), dsvHeapDesc); // Describe and create a constant buffer view (CBV), Shader resource // view (SRV), and unordered access view (UAV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {}; srvHeapDesc.NumDescriptors = 2048; srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; gDX.srvHeap = new DXHeap(gDX.device.Get(), srvHeapDesc); } // Create frame resources. { // Create a RTV for each frame. for (UINT n = 0; n < gDX.FrameCount; n++) { ThrowIfFailed(gDX.swapChain->GetBuffer(n, IID_PPV_ARGS(&gDX.renderTargets[n]))); gDX.scanbufferRtv[n] = gDX.rtvHeap->alloc(); gDX.device->CreateRenderTargetView(gDX.renderTargets[n].Get(), nullptr, *gDX.scanbufferRtv[n]); } } // Create command allocators. { for (UINT n = 0; n < gDX.FrameCount; n++) { ThrowIfFailed(gDX.device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&gDX.commandAllocator[n]))); } } // Create the root signature. { CD3DX12_DESCRIPTOR_RANGE ranges[1]; ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); CD3DX12_ROOT_PARAMETER rootParameters[1]; rootParameters[0].InitAsDescriptorTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_PIXEL); 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; CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc; rootSignatureDesc.Init(_countof(rootParameters), rootParameters, 1, &sampler, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); ComPtr<ID3DBlob> signature; ComPtr<ID3DBlob> error; ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); ThrowIfFailed(gDX.device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&gDX.rootSignature))); } // Create the pipeline state, which includes compiling and loading shaders. { ComPtr<ID3DBlob> vertexShader; ComPtr<ID3DBlob> pixelShader; #ifdef _DEBUG // Enable better shader debugging with the graphics debugging tools. UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; #else UINT compileFlags = 0; #endif ThrowIfFailed(D3DCompileFromFile(L"resources/shaders/screendraw.hlsl", nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &vertexShader, nullptr)); ThrowIfFailed(D3DCompileFromFile(L"resources/shaders/screendraw.hlsl", nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, &pixelShader, nullptr)); // Define the vertex input layout. D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } }; { D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) }; psoDesc.pRootSignature = gDX.rootSignature.Get(); psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()), vertexShader->GetBufferSize() }; psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()), pixelShader->GetBufferSize() }; psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); psoDesc.DepthStencilState.DepthEnable = FALSE; psoDesc.DepthStencilState.StencilEnable = FALSE; psoDesc.SampleMask = UINT_MAX; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; psoDesc.NumRenderTargets = 1; psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; psoDesc.SampleDesc.Count = 1; ThrowIfFailed(gDX.device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&gDX.emuPipelineState))); } } gDX.pipelineMgr = new DXPipelineMgr(); // Create the command list. gDX.frameIndex = gDX.swapChain->GetCurrentBackBufferIndex(); ThrowIfFailed(gDX.device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, gDX.commandAllocator[gDX.frameIndex].Get(), gDX.emuPipelineState.Get(), IID_PPV_ARGS(&gDX.commandList))); { #define SCREENSPACE(x, y) { -1 + ((x) / (float)platform::ui::width()) * 2, 1 - ((y) / (float)platform::ui::height()) * 2, 0.0f } float tvX = 0; float tvY = 0; float tvWidth = (float)platform::ui::tvWidth(); float tvHeight = (float)platform::ui::tvHeight(); float drcX = ((float)platform::ui::tvWidth() - (float)platform::ui::drcWidth()) / 2; float drcY = (float)platform::ui::tvHeight(); float drcWidth = (float)platform::ui::drcWidth(); float drcHeight = (float)platform::ui::drcHeight(); struct Vertex { XMFLOAT3 pos; XMFLOAT2 uv; } triangleVertices[] = { { SCREENSPACE(tvX, tvY + tvHeight),{ 0.0f, 1.0f } }, { SCREENSPACE(tvX, tvY),{ 0.0f, 0.0f } }, { SCREENSPACE(tvX + tvWidth, tvY + tvHeight),{ 1.0f, 1.0f } }, { SCREENSPACE(tvX + tvWidth, tvY),{ 1.0f, 0.0f } }, { SCREENSPACE(drcX, drcY + drcHeight),{ 0.0f, 1.0f } }, { SCREENSPACE(drcX, drcY),{ 0.0f, 0.0f } }, { SCREENSPACE(drcX + drcWidth, drcY + drcHeight),{ 1.0f, 1.0f } }, { SCREENSPACE(drcX + drcWidth, drcY),{ 1.0f, 0.0f } }, }; #undef SCREENSPACE const UINT vertexBufferSize = sizeof(triangleVertices); // Note: using upload heaps to transfer static data like vert buffers is not // recommended. Every time the GPU needs it, the upload heap will be marshalled // over. Please read up on Default Heap usage. An upload heap is used here for // code simplicity and because there are very few verts to actually transfer. ThrowIfFailed(gDX.device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&gDX.vertexBuffer))); // Copy the triangle data to the vertex buffer. UINT8* pVertexDataBegin; ThrowIfFailed(gDX.vertexBuffer->Map(0, nullptr, reinterpret_cast<void**>(&pVertexDataBegin))); memcpy(pVertexDataBegin, triangleVertices, sizeof(triangleVertices)); gDX.vertexBuffer->Unmap(0, nullptr); // Initialize the vertex buffer view. gDX.vertexBufferView.BufferLocation = gDX.vertexBuffer->GetGPUVirtualAddress(); gDX.vertexBufferView.StrideInBytes = sizeof(Vertex); gDX.vertexBufferView.SizeInBytes = vertexBufferSize; } // 10MB Temporary Vertex Buffer gDX.ppcVertexBuffer = new DXDynBuffer(gDX.device.Get(), 10 * 1024 * 1024); // Close the command list and execute it to begin the initial GPU setup. ThrowIfFailed(gDX.commandList->Close()); ID3D12CommandList* ppCommandLists[] = { gDX.commandList.Get() }; gDX.commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); // Create synchronization objects. { ThrowIfFailed(gDX.device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&gDX.fence))); // Create an event handle to use for frame synchronization. gDX.fenceEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS); if (gDX.fenceEvent == nullptr) { ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); } // Wait for frame completion gDX.swapCount++; const uint64_t fenceValue = gDX.swapCount; ThrowIfFailed(gDX.commandQueue->Signal(gDX.fence.Get(), fenceValue)); if (gDX.fence->GetCompletedValue() < gDX.swapCount) { ThrowIfFailed(gDX.fence->SetEventOnCompletion(gDX.swapCount, gDX.fenceEvent)); WaitForSingleObject(gDX.fenceEvent, INFINITE); } } _beginFrame(); }
HRESULT BasicFileOpen(PWSTR* filePath) { // CoCreate the File Open Dialog object. IFileDialog *pfd = NULL; HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd)); if (SUCCEEDED(hr)) { // Create an event handling object, and hook it up to the dialog. IFileDialogEvents *pfde = NULL; //DWORD dwCookie; // Set the options on the dialog. DWORD dwFlags; // Before setting, always get the options first in order // not to override existing options. hr = pfd->GetOptions(&dwFlags); if (SUCCEEDED(hr)) { // In this case, get shell items only for file system items. hr = pfd->SetOptions(dwFlags | FOS_FORCEFILESYSTEM); if (SUCCEEDED(hr)) { static const COMDLG_FILTERSPEC c_rgSaveTypes[] = { {L"Executable Files(*.exe)", L"*.exe"}, }; // Set the file types to display only. // Notice that this is a 1-based array. hr = pfd->SetFileTypes(ARRAYSIZE(c_rgSaveTypes), c_rgSaveTypes); if (SUCCEEDED(hr)) { // Set the selected file type index to Word Docs for this example. hr = pfd->SetFileTypeIndex(1); if (SUCCEEDED(hr)) { // Set the default extension to be ".doc" file. hr = pfd->SetDefaultExtension(L"exe"); if (SUCCEEDED(hr)) { // Show the dialog hr = pfd->Show(g_hwnd); if (SUCCEEDED(hr)) { // Obtain the result once the user clicks // the 'Open' button. // The result is an IShellItem object. IShellItem *psiResult; hr = pfd->GetResult(&psiResult); if (SUCCEEDED(hr)) { // We are just going to print out the // name of the file for sample sake. PWSTR pszFilePath = NULL; hr = psiResult->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath); if (SUCCEEDED(hr)) { *filePath=pszFilePath; } psiResult->Release(); } } } } } } } pfd->Release(); } else { hr=E_OUTOFMEMORY; OPENFILENAME ofn; LPWSTR pszFile=(LPWSTR)CoTaskMemAlloc(260*2); if(pszFile!=NULL) { memset1(&ofn,0,sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = g_hwnd; ofn.lpstrFile = pszFile; // Set lpstrFile[0] to '\0' so that GetOpenFileName does not // use the contents of szFile to initialize itself. ofn.lpstrFile[0] = L'\0'; ofn.nMaxFile = 260; ofn.lpstrFilter = L"Executable Files(*.exe)\0*.exe\0"; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; if (GetOpenFileName(&ofn)==TRUE) { *filePath=pszFile; hr=0; } } } return hr; }
/** * @brief * Constructor */ SwapChain::SwapChain(Direct3D11Renderer &direct3D11Renderer, handle nativeWindowHandle) : ISwapChain(direct3D11Renderer), mDxgiSwapChain(nullptr), mD3D11RenderTargetView(nullptr), mD3D11DepthStencilView(nullptr) { // Get the Direct3D 11 device instance ID3D11Device *d3d11Device = direct3D11Renderer.getD3D11Device(); // Get the native window handle const HWND hWnd = reinterpret_cast<HWND>(nativeWindowHandle); // Get a IDXGIFactory1 instance IDXGIDevice *dxgiDevice = nullptr; IDXGIAdapter *dxgiAdapter = nullptr; IDXGIFactory1 *dxgiFactory1 = nullptr; d3d11Device->QueryInterface(&dxgiDevice); dxgiDevice->GetAdapter(&dxgiAdapter); dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory1)); dxgiAdapter->Release(); dxgiDevice->Release(); // Get the width and height of the given native window and ensure they are never ever zero // -> See "getSafeWidthAndHeight()"-method comments for details long width = 1; long height = 1; { // Get the client rectangle of the given native window RECT rect; ::GetClientRect(hWnd, &rect); // Get the width and height... width = rect.right - rect.left; height = rect.bottom - rect.top; // ... and ensure that none of them is ever zero if (width < 1) { width = 1; } if (height < 1) { height = 1; } } // Create the swap chain DXGI_SWAP_CHAIN_DESC dxgiSwapChainDesc; ::ZeroMemory(&dxgiSwapChainDesc, sizeof(dxgiSwapChainDesc)); dxgiSwapChainDesc.BufferCount = 1; dxgiSwapChainDesc.BufferDesc.Width = static_cast<UINT>(width); dxgiSwapChainDesc.BufferDesc.Height = static_cast<UINT>(height); dxgiSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; dxgiSwapChainDesc.BufferDesc.RefreshRate.Numerator = 60; dxgiSwapChainDesc.BufferDesc.RefreshRate.Denominator = 1; dxgiSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; dxgiSwapChainDesc.OutputWindow = hWnd; dxgiSwapChainDesc.SampleDesc.Count = 1; dxgiSwapChainDesc.SampleDesc.Quality = 0; dxgiSwapChainDesc.Windowed = TRUE; dxgiFactory1->CreateSwapChain(d3d11Device, &dxgiSwapChainDesc, &mDxgiSwapChain); dxgiFactory1->Release(); // Disable alt-return for automatic fullscreen state change // -> We handle this manually to have more control over it dxgiFactory1->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); // Create the Direct3D 11 views if (nullptr != mDxgiSwapChain) { createDirect3D11Views(); } // Assign a default name to the resource for debugging purposes #ifndef DIRECT3D11RENDERER_NO_DEBUG setDebugName("Swap chain"); #endif }
// Writes properties on the user specified object. void WriteContentProperties( IPortableDevice* pDevice) { if (pDevice == NULL) { printf("! A NULL IPortableDevice interface pointer was received\n"); return; } //<SnippetContentProp3> HRESULT hr = S_OK; WCHAR szSelection[81] = {0}; WCHAR szNewObjectName[81] = {0}; CComPtr<IPortableDeviceProperties> pProperties; CComPtr<IPortableDeviceContent> pContent; CComPtr<IPortableDeviceValues> pObjectPropertiesToWrite; CComPtr<IPortableDeviceValues> pPropertyWriteResults; CComPtr<IPortableDeviceValues> pAttributes; BOOL bCanWrite = FALSE; // Prompt user to enter an object identifier on the device to write properties on. printf("Enter the identifer of the object you wish to write properties on.\n>"); hr = StringCbGetsW(szSelection,sizeof(szSelection)); if (FAILED(hr)) { printf("An invalid object identifier was specified, aborting property reading\n"); } //</SnippetContentProp3> // 1) Get an IPortableDeviceContent interface from the IPortableDevice interface to // access the content-specific methods. //<SnippetContentProp4> if (SUCCEEDED(hr)) { hr = pDevice->Content(&pContent); if (FAILED(hr)) { printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr); } } // 2) Get an IPortableDeviceProperties interface from the IPortableDeviceContent interface // to access the property-specific methods. if (SUCCEEDED(hr)) { hr = pContent->Properties(&pProperties); if (FAILED(hr)) { printf("! Failed to get IPortableDeviceProperties from IPortableDevice, hr = 0x%lx\n",hr); } } // 3) Check the property attributes to see if we can write/change the WPD_OBJECT_NAME property. if (SUCCEEDED(hr)) { hr = pProperties->GetPropertyAttributes(szSelection, WPD_OBJECT_NAME, &pAttributes); if (SUCCEEDED(hr)) { hr = pAttributes->GetBoolValue(WPD_PROPERTY_ATTRIBUTE_CAN_WRITE, &bCanWrite); if (SUCCEEDED(hr)) { if (bCanWrite) { printf("The attribute WPD_PROPERTY_ATTRIBUTE_CAN_WRITE for the WPD_OBJECT_NAME reports TRUE\nThis means that the property can be changed/updated\n\n"); } else { printf("The attribute WPD_PROPERTY_ATTRIBUTE_CAN_WRITE for the WPD_OBJECT_NAME reports FALSE\nThis means that the property cannot be changed/updated\n\n"); } } else { printf("! Failed to get the WPD_PROPERTY_ATTRIBUTE_CAN_WRITE value from WPD_OBJECT_NAME on object '%ws', hr = 0x%lx\n",szSelection, hr); } } } //</SnippetContentProp4> // 4) Prompt the user for the new value of the WPD_OBJECT_NAME property only if the property attributes report // that it can be changed/updated. //<SnippetContentProp5> if (bCanWrite) { printf("Enter the new WPD_OBJECT_NAME for the object '%ws'.\n>",szSelection); hr = StringCbGetsW(szNewObjectName,sizeof(szNewObjectName)); if (FAILED(hr)) { printf("An invalid object name was specified, aborting property writing\n"); } // 5) CoCreate an IPortableDeviceValues interface to hold the the property values // we wish to write. if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pObjectPropertiesToWrite)); if (SUCCEEDED(hr)) { if (pObjectPropertiesToWrite != NULL) { hr = pObjectPropertiesToWrite->SetStringValue(WPD_OBJECT_NAME, szNewObjectName); if (FAILED(hr)) { printf("! Failed to add WPD_OBJECT_NAME to IPortableDeviceValues, hr= 0x%lx\n", hr); } } } } //</SnippetContentProp5> // 6) Call SetValues() passing the collection of specified PROPERTYKEYs. //<SnippetContentProp6> if (SUCCEEDED(hr)) { hr = pProperties->SetValues(szSelection, // The object whose properties we are reading pObjectPropertiesToWrite, // The properties we want to read &pPropertyWriteResults); // Driver supplied property result values for the property read operation if (FAILED(hr)) { printf("! Failed to set properties for object '%ws', hr= 0x%lx\n", szSelection, hr); } else { printf("The WPD_OBJECT_NAME property on object '%ws' was written successfully (Read the properties again to see the updated value)\n", szSelection); } } //</SnippetContentProp6> } }
int BaseGraphicsState::Initialize(ID3D12Device& device, const GfxGraphicsStateDesc& desc) { D3D12_INPUT_ELEMENT_DESC elements[32]; SI_ASSERT(desc.m_inputElementCount < ArraySize(elements)); uint32_t elementCont = SI::Min((uint32_t)desc.m_inputElementCount, (uint32_t)ArraySize(elements)); for(uint32_t e=0; e<elementCont; ++e) { D3D12_INPUT_ELEMENT_DESC& outElem = elements[e]; const GfxInputElement& inElem = desc.m_inputElements[e]; outElem.SemanticName = inElem.m_semanticsName; outElem.SemanticIndex = inElem.m_semanticsId; outElem.Format = SI::GetDx12Format(inElem.m_format); outElem.InputSlot = inElem.m_inputSlot; outElem.AlignedByteOffset = inElem.m_alignedByteOffset; outElem.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; outElem.InstanceDataStepRate = 0; } const BaseShader* vertexShader = desc.m_vertexShader->GetBaseShader(); const BaseShader* pixelShader = desc.m_pixelShader->GetBaseShader(); D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.InputLayout = { elements, elementCont }; psoDesc.pRootSignature = desc.m_rootSignature->GetBaseRootSignature()->GetComPtrRootSignature().Get(); psoDesc.VS.pShaderBytecode = vertexShader? vertexShader->GetBinary() : nullptr; psoDesc.VS.BytecodeLength = vertexShader? vertexShader->GetBinarySize() : 0; psoDesc.PS.pShaderBytecode = pixelShader? pixelShader->GetBinary() : nullptr; psoDesc.PS.BytecodeLength = pixelShader? pixelShader->GetBinarySize() : 0; psoDesc.RasterizerState.FillMode = GetDx12FillMode(desc.m_fillMode); psoDesc.RasterizerState.CullMode = GetDx12CullMode(desc.m_cullMode); psoDesc.RasterizerState.FrontCounterClockwise = desc.m_frontCounterClockwise? TRUE : FALSE; psoDesc.RasterizerState.DepthBias = desc.m_depthBias; psoDesc.RasterizerState.DepthBiasClamp = desc.m_depthBiasClamp; psoDesc.RasterizerState.SlopeScaledDepthBias = desc.m_slopeScaledDepthBias; psoDesc.RasterizerState.DepthClipEnable = TRUE; psoDesc.RasterizerState.MultisampleEnable = FALSE; psoDesc.RasterizerState.AntialiasedLineEnable = FALSE; psoDesc.RasterizerState.ForcedSampleCount = 0; psoDesc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; psoDesc.SampleMask = UINT_MAX; psoDesc.PrimitiveTopologyType = GetDx12PrimitiveTopologyType(desc.m_primitiveTopologyType); psoDesc.SampleDesc.Count = 1; psoDesc.NumRenderTargets = desc.m_renderTargetCount; psoDesc.BlendState.AlphaToCoverageEnable = FALSE; psoDesc.BlendState.IndependentBlendEnable = FALSE; psoDesc.DepthStencilState.DepthEnable = desc.m_depthEnable? TRUE : FALSE; psoDesc.DepthStencilState.StencilEnable = desc.m_stencilEnable? TRUE : FALSE; if(psoDesc.DepthStencilState.DepthEnable) { psoDesc.DepthStencilState.DepthWriteMask = GetDx12DepthWriteMask(desc.m_depthWriteMask); psoDesc.DepthStencilState.DepthFunc = GetDx12ComparisonFunc(desc.m_depthFunc); } SI_ASSERT(desc.m_renderTargetCount <= D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT); UINT blendRtCount = psoDesc.BlendState.IndependentBlendEnable? psoDesc.NumRenderTargets : 1; for (UINT rt = 0; rt<blendRtCount; ++rt) { D3D12_RENDER_TARGET_BLEND_DESC& outBlend = psoDesc.BlendState.RenderTarget[rt]; const GfxRenderTargetBlendDesc& inBlend = desc.m_rtvBlend[rt]; outBlend.BlendEnable = inBlend.m_blendEnable? TRUE : FALSE; outBlend.LogicOpEnable = inBlend.m_logicOpEnable? TRUE : FALSE; outBlend.SrcBlend = GetDx12Blend(inBlend.m_srcBlend); outBlend.DestBlend = GetDx12Blend(inBlend.m_destBlend); outBlend.BlendOp = GetDx12BlendOp(inBlend.m_blendOp); outBlend.SrcBlendAlpha = GetDx12Blend(inBlend.m_srcBlendAlpha); outBlend.DestBlendAlpha = GetDx12Blend(inBlend.m_destBlendAlpha); outBlend.BlendOpAlpha = GetDx12BlendOp(inBlend.m_blendOpAlpha); outBlend.LogicOp = GetDx12LogicOp(inBlend.m_logicOp); outBlend.RenderTargetWriteMask = GetDx12RenderTargetWriteMask(inBlend.m_rtWriteMask); } for (UINT rt = 0; rt<psoDesc.NumRenderTargets; ++rt) { psoDesc.RTVFormats[rt] = GetDx12Format(desc.m_rtvFormats[rt]); } psoDesc.DSVFormat = GetDx12Format(desc.m_dsvFormat); HRESULT hr = device.CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState)); if(FAILED(hr)) { SI_ASSERT(0); return -1; } if(desc.m_name) { wchar_t wName[64]; wName[0] = 0; size_t num = 0; errno_t ret = mbstowcs_s(&num, wName, desc.m_name, ArraySize(wName)); if(ret == 0) { m_pipelineState->SetName(wName); } } return 0; }
// Reads a set of properties for all objects. void ReadContentPropertiesBulk( IPortableDevice* pDevice) { if (pDevice == NULL) { printf("! A NULL IPortableDevice interface pointer was received\n"); return; } HRESULT hr = S_OK; GUID guidContext = GUID_NULL; CGetBulkValuesCallback* pCallback = NULL; CComPtr<IPortableDeviceProperties> pProperties; CComPtr<IPortableDevicePropertiesBulk> pPropertiesBulk; CComPtr<IPortableDeviceValues> pObjectProperties; CComPtr<IPortableDeviceContent> pContent; CComPtr<IPortableDeviceKeyCollection> pPropertiesToRead; CComPtr<IPortableDevicePropVariantCollection> pObjectIDs; // 1) Get an IPortableDeviceContent interface from the IPortableDevice interface to // access the content-specific methods. hr = pDevice->Content(&pContent); if (FAILED(hr)) { printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr); } // 2) Get an IPortableDeviceProperties interface from the IPortableDeviceContent interface // to access the property-specific methods. if (SUCCEEDED(hr)) { hr = pContent->Properties(&pProperties); if (FAILED(hr)) { printf("! Failed to get IPortableDeviceProperties from IPortableDevice, hr = 0x%lx\n",hr); } } // 3) Check to see if the driver supports BULK property operations by call QueryInterface // on the IPortableDeviceProperties interface for IPortableDevicePropertiesBulk if (SUCCEEDED(hr)) { hr = pProperties->QueryInterface(IID_PPV_ARGS(&pPropertiesBulk)); if (FAILED(hr)) { printf("This driver does not support BULK property operations.\n"); } } // 4) CoCreate an IPortableDeviceKeyCollection interface to hold the the property keys // we wish to read. if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_PortableDeviceKeyCollection, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pPropertiesToRead)); if (FAILED(hr)) { printf("! Failed to CoCreate IPortableDeviceKeyCollection to hold the property keys to read, hr = 0x%lx\n",hr); } } if (SUCCEEDED(hr)) { // 5) Populate the IPortableDeviceKeyCollection with the keys we wish to read. // NOTE: We are not handling any special error cases here so we can proceed with // adding as many of the target properties as we can. if (pPropertiesToRead != NULL) { HRESULT hrTemp = S_OK; hrTemp = pPropertiesToRead->Add(WPD_OBJECT_PARENT_ID); if (FAILED(hrTemp)) { printf("! Failed to add WPD_OBJECT_PARENT_ID to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp); } hrTemp = pPropertiesToRead->Add(WPD_OBJECT_NAME); if (FAILED(hrTemp)) { printf("! Failed to add WPD_OBJECT_NAME to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp); } hrTemp = pPropertiesToRead->Add(WPD_OBJECT_PERSISTENT_UNIQUE_ID); if (FAILED(hrTemp)) { printf("! Failed to add WPD_OBJECT_PERSISTENT_UNIQUE_ID to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp); } hrTemp = pPropertiesToRead->Add(WPD_OBJECT_FORMAT); if (FAILED(hrTemp)) { printf("! Failed to add WPD_OBJECT_FORMAT to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp); } hrTemp = pPropertiesToRead->Add(WPD_OBJECT_CONTENT_TYPE); if (FAILED(hrTemp)) { printf("! Failed to add WPD_OBJECT_CONTENT_TYPE to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp); } } } // 6) Create an instance of the IPortableDevicePropertiesBulkCallback object. if (SUCCEEDED(hr)) { pCallback = new (std::nothrow) CGetBulkValuesCallback(); if (pCallback == NULL) { hr = E_OUTOFMEMORY; printf("! Failed to allocate CGetBulkValuesCallback, hr = 0x%lx\n", hr); } } // 7) Call our helper function CreateIPortableDevicePropVariantCollectionWithAllObjectIDs // to enumerate and create an IPortableDevicePropVariantCollection with the object // identifiers needed to perform the bulk operation on. if (SUCCEEDED(hr)) { hr = CreateIPortableDevicePropVariantCollectionWithAllObjectIDs(pContent, &pObjectIDs); } // 8) Call QueueGetValuesByObjectList to initialize the Asynchronous // property operation. if (SUCCEEDED(hr)) { hr = pPropertiesBulk->QueueGetValuesByObjectList(pObjectIDs, pPropertiesToRead, pCallback, &guidContext); // 9) Call Start() to actually being the property operation if(SUCCEEDED(hr)) { // Cleanup any previously created global event handles. if (g_hBulkPropertyOperationEvent != NULL) { CloseHandle(g_hBulkPropertyOperationEvent); g_hBulkPropertyOperationEvent = NULL; } // In order to create a simpler to follow example we create and wait infinitly // for the bulk property operation to complete and ignore any errors. // Production code should be written in a more robust manner. // Create the global event handle to wait on for the bulk operation // to complete. g_hBulkPropertyOperationEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (g_hBulkPropertyOperationEvent != NULL) { // Call Start() to actually being the Asynchronous bulk operation. hr = pPropertiesBulk->Start(guidContext); if(FAILED(hr)) { printf("! Failed to start property operation, hr = 0x%lx\n", hr); } } else { printf("! Failed to create the global event handle to wait on for the bulk operation. Aborting operation.\n"); } } else { printf("! QueueGetValuesByObjectList Failed, hr = 0x%lx\n", hr); } } // In order to create a simpler to follow example we will wait infinitly for the operation // to complete and ignore any errors. Production code should be written in a more // robust manner. if (SUCCEEDED(hr)) { if (g_hBulkPropertyOperationEvent != NULL) { WaitForSingleObject(g_hBulkPropertyOperationEvent, INFINITE); } } if (pCallback != NULL) { pCallback->Release(); pCallback = NULL; } // Cleanup any created global event handles before exiting.. if (g_hBulkPropertyOperationEvent != NULL) { CloseHandle(g_hBulkPropertyOperationEvent); g_hBulkPropertyOperationEvent = NULL; } }
void loadAssets() { // // handles to vert and pixel shaders // ComPtr<ID3DBlob> blobShaderVert, blobShaderPixel; // // compile shaders // D3DCompileFromFile(L"shaders.hlsl", nullptr, nullptr, "VShader", "vs_5_0", 0, 0, blobShaderVert.GetAddressOf(), nullptr); D3DCompileFromFile(L"shaders.hlsl", nullptr, nullptr, "PShader", "ps_5_0", 0, 0, blobShaderPixel.GetAddressOf(), nullptr); // // create input layout // D3D12_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_PER_VERTEX_DATA, 0 } }; UINT numElements = sizeof(layout) / sizeof(layout[0]); // // create an empty root signature // ComPtr<ID3DBlob> pOutBlob, pErrorBlob; D3D12_ROOT_SIGNATURE_DESC descRootSignature; descRootSignature.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); D3D12SerializeRootSignature(&descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, pOutBlob.GetAddressOf(), pErrorBlob.GetAddressOf()); mDevice->CreateRootSignature(0, pOutBlob->GetBufferPointer(), pOutBlob->GetBufferSize(), IID_PPV_ARGS(mRootSignature.GetAddressOf())); // // create a PSO description // D3D12_GRAPHICS_PIPELINE_STATE_DESC descPso; ZeroMemory(&descPso, sizeof(descPso)); descPso.InputLayout = { layout, numElements }; descPso.pRootSignature = mRootSignature.Get(); descPso.VS = { reinterpret_cast<BYTE*>(blobShaderVert->GetBufferPointer()), blobShaderVert->GetBufferSize() }; descPso.PS = { reinterpret_cast<BYTE*>(blobShaderPixel->GetBufferPointer()), blobShaderPixel->GetBufferSize() }; descPso.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); descPso.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); descPso.DepthStencilState.DepthEnable = FALSE; descPso.DepthStencilState.StencilEnable = FALSE; descPso.SampleMask = UINT_MAX; descPso.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; descPso.NumRenderTargets = 1; descPso.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; descPso.SampleDesc.Count = 1; // // create the actual PSO // mDevice->CreateGraphicsPipelineState(&descPso, IID_PPV_ARGS(mPSO.GetAddressOf())); // // create descriptor heap // D3D12_DESCRIPTOR_HEAP_DESC descHeap = {}; descHeap.NumDescriptors = 1; descHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; descHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; mDevice->CreateDescriptorHeap(&descHeap, IID_PPV_ARGS(mDescriptorHeap.GetAddressOf())); // // create command list // mDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, mCommandAllocator.Get(), mPSO.Get(), IID_PPV_ARGS(mCommandList.GetAddressOf())); // // create backbuffer/rendertarget // mSwapChain->GetBuffer(0, IID_PPV_ARGS(mRenderTarget.GetAddressOf())); mDevice->CreateRenderTargetView(mRenderTarget.Get(), nullptr, mDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); // // set the viewport // mViewPort = { 0.0f, 0.0f, static_cast<float>(mWidth), static_cast<float>(mHeight), 0.0f, 1.0f }; // // create scissor rectangle // mRectScissor = { 0, 0, mWidth, mHeight }; // // create geometry for a triangle // VERTEX triangleVerts[] = { { 0.0f, 0.5f, 0.0f,{ 1.0f, 0.0f, 0.0f, 1.0f } }, { 0.45f, -0.5, 0.0f,{ 0.0f, 1.0f, 0.0f, 1.0f } }, { -0.45f, -0.5f, 0.0f,{ 0.0f, 0.0f, 1.0f, 1.0f } } }; // // actually create the vert buffer // Note: using upload heaps to transfer static data like vert buffers is not recommended. // Every time the GPU needs it, the upload heap will be marshalled over. Please read up on Default Heap usage. // An upload heap is used here for code simplicity and because there are very few verts to actually transfer // mDevice->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(3 * sizeof(VERTEX)), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, // Clear value IID_PPV_ARGS(mBufVerts.GetAddressOf())); // // copy the triangle data to the vertex buffer // UINT8* dataBegin; mBufVerts->Map(0, nullptr, reinterpret_cast<void**>(&dataBegin)); memcpy(dataBegin, triangleVerts, sizeof(triangleVerts)); mBufVerts->Unmap(0, nullptr); // // create vertex buffer view // mDescViewBufVert.BufferLocation = mBufVerts->GetGPUVirtualAddress(); mDescViewBufVert.StrideInBytes = sizeof(VERTEX); mDescViewBufVert.SizeInBytes = sizeof(triangleVerts); // // create fencing object // mDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(mFence.GetAddressOf())); mCurrentFence = 1; // // close the command list and use it to execute the initial GPU setup // mCommandList->Close(); ID3D12CommandList* ppCommandLists[] = { mCommandList.Get() }; mCommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); // // create event handle // mHandleEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS); // // wait for the command list to execute; we are reusing the same command list in our main loop but for now, // we just want to wait for setup to complete before continuing // waitForGPU(); }
// Reads properties for the user specified object. void ReadContentProperties( IPortableDevice* pDevice) { if (pDevice == NULL) { printf("! A NULL IPortableDevice interface pointer was received\n"); return; } HRESULT hr = S_OK; WCHAR szSelection[81] = {0}; CComPtr<IPortableDeviceProperties> pProperties; CComPtr<IPortableDeviceValues> pObjectProperties; CComPtr<IPortableDeviceContent> pContent; CComPtr<IPortableDeviceKeyCollection> pPropertiesToRead; // Prompt user to enter an object identifier on the device to read properties from. printf("Enter the identifer of the object you wish to read properties from.\n>"); hr = StringCbGetsW(szSelection,sizeof(szSelection)); if (FAILED(hr)) { printf("An invalid object identifier was specified, aborting property reading\n"); } // 1) Get an IPortableDeviceContent interface from the IPortableDevice interface to // access the content-specific methods. if (SUCCEEDED(hr)) { hr = pDevice->Content(&pContent); if (FAILED(hr)) { printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr); } } // 2) Get an IPortableDeviceProperties interface from the IPortableDeviceContent interface // to access the property-specific methods. if (SUCCEEDED(hr)) { hr = pContent->Properties(&pProperties); if (FAILED(hr)) { printf("! Failed to get IPortableDeviceProperties from IPortableDevice, hr = 0x%lx\n",hr); } } // 3) CoCreate an IPortableDeviceKeyCollection interface to hold the the property keys // we wish to read. //<SnippetContentProp1> hr = CoCreateInstance(CLSID_PortableDeviceKeyCollection, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pPropertiesToRead)); if (SUCCEEDED(hr)) { // 4) Populate the IPortableDeviceKeyCollection with the keys we wish to read. // NOTE: We are not handling any special error cases here so we can proceed with // adding as many of the target properties as we can. if (pPropertiesToRead != NULL) { HRESULT hrTemp = S_OK; hrTemp = pPropertiesToRead->Add(WPD_OBJECT_PARENT_ID); if (FAILED(hrTemp)) { printf("! Failed to add WPD_OBJECT_PARENT_ID to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp); } hrTemp = pPropertiesToRead->Add(WPD_OBJECT_NAME); if (FAILED(hrTemp)) { printf("! Failed to add WPD_OBJECT_NAME to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp); } hrTemp = pPropertiesToRead->Add(WPD_OBJECT_PERSISTENT_UNIQUE_ID); if (FAILED(hrTemp)) { printf("! Failed to add WPD_OBJECT_PERSISTENT_UNIQUE_ID to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp); } hrTemp = pPropertiesToRead->Add(WPD_OBJECT_FORMAT); if (FAILED(hrTemp)) { printf("! Failed to add WPD_OBJECT_FORMAT to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp); } hrTemp = pPropertiesToRead->Add(WPD_OBJECT_CONTENT_TYPE); if (FAILED(hrTemp)) { printf("! Failed to add WPD_OBJECT_CONTENT_TYPE to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp); } } } //</SnippetContentProp1> // 5) Call GetValues() passing the collection of specified PROPERTYKEYs. //<SnippetContentProp2> if (SUCCEEDED(hr)) { hr = pProperties->GetValues(szSelection, // The object whose properties we are reading pPropertiesToRead, // The properties we want to read &pObjectProperties); // Driver supplied property values for the specified object if (FAILED(hr)) { printf("! Failed to get all properties for object '%ws', hr= 0x%lx\n", szSelection, hr); } } //</SnippetContentProp2> // 6) Display the returned property values to the user if (SUCCEEDED(hr)) { DisplayStringProperty(pObjectProperties, WPD_OBJECT_PARENT_ID, L"WPD_OBJECT_PARENT_ID"); DisplayStringProperty(pObjectProperties, WPD_OBJECT_NAME, L"WPD_OBJECT_NAME"); DisplayStringProperty(pObjectProperties, WPD_OBJECT_PERSISTENT_UNIQUE_ID, L"WPD_OBJECT_PERSISTENT_UNIQUE_ID"); DisplayGuidProperty (pObjectProperties, WPD_OBJECT_CONTENT_TYPE, L"WPD_OBJECT_CONTENT_TYPE"); DisplayGuidProperty (pObjectProperties, WPD_OBJECT_FORMAT, L"WPD_OBJECT_FORMAT"); } }
void Read(const SmallPsoDiskDesc &key, const u8* value, u32 value_size) { if (s_cache_is_corrupted) return; D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {}; desc.GS = ShaderCache::GetGeometryShaderFromUid(key.gs_uid); if (key.using_uber_pixel_shader) { desc.PS = ShaderCache::GetPixelUberShaderFromUid(key.pus_uid); } else { desc.PS = ShaderCache::GetPixelShaderFromUid(key.ps_uid); } if (key.using_uber_vertex_shader) { desc.VS = ShaderCache::GetVertexShaderFromUid(key.vs_uid); } else { desc.VS = ShaderCache::GetVertexUberShaderFromUid(key.vus_uid); } desc.HS = ShaderCache::GetHullShaderFromUid(key.hds_uid); desc.DS = ShaderCache::GetDomainShaderFromUid(key.hds_uid); D3D::SetRootSignature(desc.GS.pShaderBytecode != nullptr, desc.HS.pShaderBytecode != nullptr, false); desc.pRootSignature = D3D::GetRootSignature(static_cast<size_t>(key.root_signature_index)); desc.RTVFormats[0] = key.rtformat; // This state changes in PSTextureEncoder::Encode. desc.DSVFormat = DXGI_FORMAT_D32_FLOAT; // This state changes in PSTextureEncoder::Encode. desc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF; desc.NumRenderTargets = 1; desc.SampleMask = UINT_MAX; desc.SampleDesc = key.sample_desc; if (!desc.PS.pShaderBytecode || !desc.VS.pShaderBytecode) { s_cache_is_corrupted = true; return; } BlendingState blend_state = {}; blend_state.hex = key.blend_state_hex; desc.BlendState = StateCache::GetDesc(blend_state); DepthState depth_stencil_state = {}; depth_stencil_state.hex = key.depth_stencil_state_hex; desc.DepthStencilState = StateCache::GetDesc(depth_stencil_state); RasterizationState rasterizer_state = {}; rasterizer_state.hex = key.rasterizer_state_hex; desc.RasterizerState = StateCache::GetDesc(rasterizer_state); desc.PrimitiveTopologyType = key.topology; // search for a cached native vertex format const PortableVertexDeclaration& native_vtx_decl = key.vertex_declaration; NativeVertexFormat* native = VertexLoaderManager::GetOrCreateMatchingFormat(native_vtx_decl); desc.InputLayout = static_cast<D3DVertexFormat*>(native)->GetActiveInputLayout(); desc.CachedPSO.CachedBlobSizeInBytes = value_size; desc.CachedPSO.pCachedBlob = value; ComPtr<ID3D12PipelineState> pso; HRESULT hr = D3D::device->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(pso.ReleaseAndGetAddressOf())); if (FAILED(hr)) { // Failure can occur if disk cache is corrupted, or a driver upgrade invalidates the existing blobs. // In this case, we need to clear the disk cache. s_cache_is_corrupted = true; return; } SmallPsoDesc small_desc = {}; small_desc.using_uber_pixel_shader = key.using_uber_pixel_shader; small_desc.using_uber_vertex_shader = key.using_uber_vertex_shader; small_desc.blend_state.hex = key.blend_state_hex; small_desc.depth_stencil_state.hex = key.depth_stencil_state_hex; small_desc.rasterizer_state.hex = key.rasterizer_state_hex; small_desc.gs_bytecode = desc.GS; small_desc.vs_bytecode = desc.VS; small_desc.ps_bytecode = desc.PS; small_desc.hs_bytecode = desc.HS; small_desc.ds_bytecode = desc.DS; small_desc.input_Layout = static_cast<D3DVertexFormat*>(native); small_desc.sample_count = key.sample_desc.Count; small_desc.rtformat = key.rtformat; s_gx_state_cache.m_small_pso_map[small_desc] = pso; }
// Load the sample assets. void D3D12PredicationQueries::LoadAssets() { // Create a root signature consisting of a single CBV parameter. { D3D12_FEATURE_DATA_ROOT_SIGNATURE featureData = {}; // This is the highest version the sample supports. If CheckFeatureSupport succeeds, the HighestVersion returned will not be greater than this. featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1; if (FAILED(m_device->CheckFeatureSupport(D3D12_FEATURE_ROOT_SIGNATURE, &featureData, sizeof(featureData)))) { featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_0; } CD3DX12_DESCRIPTOR_RANGE1 ranges[1]; CD3DX12_ROOT_PARAMETER1 rootParameters[1]; ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC); rootParameters[0].InitAsDescriptorTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_VERTEX); // Allow input layout and deny uneccessary access to certain pipeline stages. 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_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS; CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc; rootSignatureDesc.Init_1_1(_countof(rootParameters), rootParameters, 0, nullptr, rootSignatureFlags); ComPtr<ID3DBlob> signature; ComPtr<ID3DBlob> error; ThrowIfFailed(D3DX12SerializeVersionedRootSignature(&rootSignatureDesc, featureData.HighestVersion, &signature, &error)); ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature))); NAME_D3D12_OBJECT(m_rootSignature); } // Create the pipeline state, which includes compiling and loading shaders. { ComPtr<ID3DBlob> vertexShader; ComPtr<ID3DBlob> pixelShader; #if defined(_DEBUG) // Enable better shader debugging with the graphics debugging tools. UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; #else UINT compileFlags = 0; #endif ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"shaders.hlsl").c_str(), nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &vertexShader, nullptr)); ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"shaders.hlsl").c_str(), nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, &pixelShader, nullptr)); // Define the vertex input layout. D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } }; // Enable alpha blending so we can visualize the occlusion query results. CD3DX12_BLEND_DESC blendDesc(D3D12_DEFAULT); blendDesc.RenderTarget[0] = { TRUE, FALSE, D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, D3D12_LOGIC_OP_NOOP, D3D12_COLOR_WRITE_ENABLE_ALL, }; // Describe and create the graphics pipeline state objects (PSO). D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) }; psoDesc.pRootSignature = m_rootSignature.Get(); psoDesc.VS = CD3DX12_SHADER_BYTECODE(vertexShader.Get()); psoDesc.PS = CD3DX12_SHADER_BYTECODE(pixelShader.Get()); psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); psoDesc.BlendState = blendDesc; psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); psoDesc.SampleMask = UINT_MAX; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; psoDesc.NumRenderTargets = 1; psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT; psoDesc.SampleDesc.Count = 1; ThrowIfFailed(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState))); NAME_D3D12_OBJECT(m_pipelineState); // Disable color writes and depth writes for the occlusion query's state. psoDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = 0; psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; ThrowIfFailed(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_queryState))); NAME_D3D12_OBJECT(m_queryState); } // Create the command list. ThrowIfFailed(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get(), IID_PPV_ARGS(&m_commandList))); NAME_D3D12_OBJECT(m_commandList); // Note: ComPtr's are CPU objects but this resource needs to stay in scope until // the command list that references it has finished executing on the GPU. // We will flush the GPU at the end of this method to ensure the resource is not // prematurely destroyed. ComPtr<ID3D12Resource> vertexBufferUpload; // Create the vertex buffer. { // Create geometry for two quads and a bounding box for the occlusion query. // Geometry will be rendered back-to-front to support transparency in the scene. Vertex quadVertices[] = { // Far quad - in practice this would be a complex geometry. { { -0.25f, -0.25f * m_aspectRatio, 0.5f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, { { -0.25f, 0.25f * m_aspectRatio, 0.5f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, { { 0.25f, -0.25f * m_aspectRatio, 0.5f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, { { 0.25f, 0.25f * m_aspectRatio, 0.5f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // Near quad. { { -0.5f, -0.35f * m_aspectRatio, 0.0f }, { 1.0f, 0.0f, 0.0f, 0.65f } }, { { -0.5f, 0.35f * m_aspectRatio, 0.0f }, { 1.0f, 0.0f, 0.0f, 0.65f } }, { { 0.5f, -0.35f * m_aspectRatio, 0.0f }, { 1.0f, 1.0f, 0.0f, 0.65f } }, { { 0.5f, 0.35f * m_aspectRatio, 0.0f }, { 1.0f, 1.0f, 0.0f, 0.65f } }, // Far quad bounding box used for occlusion query (offset slightly to avoid z-fighting). { { -0.25f, -0.25f * m_aspectRatio, 0.4999f }, { 0.0f, 0.0f, 0.0f, 1.0f } }, { { -0.25f, 0.25f * m_aspectRatio, 0.4999f }, { 0.0f, 0.0f, 0.0f, 1.0f } }, { { 0.25f, -0.25f * m_aspectRatio, 0.4999f }, { 0.0f, 0.0f, 0.0f, 1.0f } }, { { 0.25f, 0.25f * m_aspectRatio, 0.4999f }, { 0.0f, 0.0f, 0.0f, 1.0f } }, }; const UINT vertexBufferSize = sizeof(quadVertices); ThrowIfFailed(m_device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize), D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&m_vertexBuffer))); ThrowIfFailed(m_device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&vertexBufferUpload))); NAME_D3D12_OBJECT(m_vertexBuffer); // Copy data to the intermediate upload heap and then schedule a copy // from the upload heap to the vertex buffer. D3D12_SUBRESOURCE_DATA vertexData = {}; vertexData.pData = reinterpret_cast<UINT8*>(quadVertices); vertexData.RowPitch = vertexBufferSize; vertexData.SlicePitch = vertexData.RowPitch; UpdateSubresources<1>(m_commandList.Get(), m_vertexBuffer.Get(), vertexBufferUpload.Get(), 0, 0, 1, &vertexData); m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_vertexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER)); // Initialize the vertex buffer view. m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress(); m_vertexBufferView.StrideInBytes = sizeof(Vertex); m_vertexBufferView.SizeInBytes = sizeof(quadVertices); } // Create the constant buffers. { ThrowIfFailed(m_device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(FrameCount * sizeof(m_constantBufferData)), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&m_constantBuffer))); NAME_D3D12_OBJECT(m_constantBuffer); // Initialize and map the constant buffers. We don't unmap this until the // app closes. Keeping things mapped for the lifetime of the resource is okay. ZeroMemory(&m_constantBufferData, sizeof(m_constantBufferData)); CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. ThrowIfFailed(m_constantBuffer->Map(0, &readRange, reinterpret_cast<void**>(&m_pCbvDataBegin))); ZeroMemory(m_pCbvDataBegin, FrameCount * sizeof(m_constantBufferData)); // Create constant buffer views to access the upload buffer. CD3DX12_CPU_DESCRIPTOR_HANDLE cpuHandle(m_cbvHeap->GetCPUDescriptorHandleForHeapStart()); D3D12_GPU_VIRTUAL_ADDRESS gpuAddress = m_constantBuffer->GetGPUVirtualAddress(); D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {}; cbvDesc.SizeInBytes = sizeof(SceneConstantBuffer); for (UINT n = 0; n < FrameCount; n++) { cbvDesc.BufferLocation = gpuAddress; m_device->CreateConstantBufferView(&cbvDesc, cpuHandle); cpuHandle.Offset(m_cbvSrvDescriptorSize); gpuAddress += cbvDesc.SizeInBytes; cbvDesc.BufferLocation = gpuAddress; m_device->CreateConstantBufferView(&cbvDesc, cpuHandle); cpuHandle.Offset(m_cbvSrvDescriptorSize); gpuAddress += cbvDesc.SizeInBytes; } } // Create the depth stencil view. { D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilDesc = {}; depthStencilDesc.Format = DXGI_FORMAT_D32_FLOAT; depthStencilDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; depthStencilDesc.Flags = D3D12_DSV_FLAG_NONE; D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = DXGI_FORMAT_D32_FLOAT; depthOptimizedClearValue.DepthStencil.Depth = 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D32_FLOAT, m_width, m_height, 1, 0, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL), D3D12_RESOURCE_STATE_DEPTH_WRITE, &depthOptimizedClearValue, IID_PPV_ARGS(&m_depthStencil) )); NAME_D3D12_OBJECT(m_depthStencil); m_device->CreateDepthStencilView(m_depthStencil.Get(), &depthStencilDesc, m_dsvHeap->GetCPUDescriptorHandleForHeapStart()); } // Create the query result buffer. { D3D12_RESOURCE_DESC queryResultDesc = CD3DX12_RESOURCE_DESC::Buffer(8); ThrowIfFailed(m_device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &queryResultDesc, D3D12_RESOURCE_STATE_PREDICATION, nullptr, IID_PPV_ARGS(&m_queryResult) )); NAME_D3D12_OBJECT(m_queryResult); } // Close the command list and execute it to begin the vertex buffer copy into // the default heap. ThrowIfFailed(m_commandList->Close()); ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() }; m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); // Create synchronization objects and wait until assets have been uploaded to the GPU. { ThrowIfFailed(m_device->CreateFence(m_fenceValues[m_frameIndex], D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence))); m_fenceValues[m_frameIndex]++; // Create an event handle to use for frame synchronization. m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); if (m_fenceEvent == nullptr) { ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); } // Wait for the command list to execute; we are reusing the same command // list in our main loop but for now, we just want to wait for setup to // complete before continuing. WaitForGpu(); } }
HRESULT StateCache::GetPipelineStateObjectFromCache(const SmallPsoDesc& pso_desc, ID3D12PipelineState** pso, D3D12_PRIMITIVE_TOPOLOGY_TYPE topology) { auto it = m_small_pso_map.find(pso_desc); if (it == m_small_pso_map.end()) { // Not found, create new PSO. // RootSignature, SampleMask, NumRenderTargets, RTVFormats, DSVFormat // never change so they are set in constructor and forgotten. m_current_pso_desc.GS = pso_desc.gs_bytecode; m_current_pso_desc.PS = pso_desc.ps_bytecode; m_current_pso_desc.VS = pso_desc.vs_bytecode; m_current_pso_desc.HS = pso_desc.hs_bytecode; m_current_pso_desc.DS = pso_desc.ds_bytecode; m_current_pso_desc.RTVFormats[0] = pso_desc.rtformat; m_current_pso_desc.pRootSignature = D3D::GetRootSignature(); m_current_pso_desc.BlendState = GetDesc(pso_desc.blend_state); m_current_pso_desc.DepthStencilState = GetDesc(pso_desc.depth_stencil_state); m_current_pso_desc.RasterizerState = GetDesc(pso_desc.rasterizer_state); m_current_pso_desc.PrimitiveTopologyType = topology; m_current_pso_desc.InputLayout = pso_desc.input_Layout->GetActiveInputLayout(); m_current_pso_desc.SampleDesc.Count = pso_desc.sample_count; ComPtr<ID3D12PipelineState> new_pso; HRESULT hr = D3D::device->CreateGraphicsPipelineState(&m_current_pso_desc, IID_PPV_ARGS(new_pso.ReleaseAndGetAddressOf())); if (FAILED(hr)) { CheckHR(hr); return hr; } m_small_pso_map[pso_desc] = new_pso; *pso = new_pso.Get(); if (m_enable_disk_cache) { // This contains all of the information needed to reconstruct a PSO at startup. SmallPsoDiskDesc disk_desc = {}; disk_desc.using_uber_pixel_shader = pso_desc.using_uber_pixel_shader; disk_desc.using_uber_vertex_shader = pso_desc.using_uber_vertex_shader; disk_desc.root_signature_index = static_cast<u32>(D3D::GetRootSignatureIndex()); disk_desc.blend_state_hex = pso_desc.blend_state.hex; disk_desc.depth_stencil_state_hex = pso_desc.depth_stencil_state.hex; disk_desc.rasterizer_state_hex = pso_desc.rasterizer_state.hex; disk_desc.gs_uid = ShaderCache::GetActiveGeometryShaderUid(); if (pso_desc.using_uber_pixel_shader) { disk_desc.pus_uid = ShaderCache::GetActivePixelUberShaderUid(); } else { disk_desc.ps_uid = ShaderCache::GetActivePixelShaderUid(); } if (pso_desc.using_uber_vertex_shader) { disk_desc.vus_uid = ShaderCache::GetActiveVertexUberShaderUid(); } else { disk_desc.vs_uid = ShaderCache::GetActiveVertexShaderUid(); } disk_desc.hds_uid = ShaderCache::GetActiveTessellationShaderUid(); disk_desc.vertex_declaration = pso_desc.input_Layout->GetVertexDeclaration(); disk_desc.topology = topology; disk_desc.sample_desc.Count = g_ActiveConfig.iMultisamples; disk_desc.rtformat = pso_desc.rtformat; // This shouldn't fail.. but if it does, don't cache to disk. ComPtr<ID3DBlob> psoBlob; hr = new_pso->GetCachedBlob(psoBlob.ReleaseAndGetAddressOf()); if (SUCCEEDED(hr)) { s_pso_disk_cache.Append(disk_desc, reinterpret_cast<const u8*>(psoBlob->GetBufferPointer()), static_cast<u32>(psoBlob->GetBufferSize())); } } } else { *pso = it->second.Get(); } return S_OK; }
BOOL CPPageOutput::OnInitDialog() { __super::OnInitDialog(); SetHandCursor(m_hWnd, IDC_AUDRND_COMBO); const CAppSettings& s = AfxGetAppSettings(); const CRenderersSettings& r = s.m_RenderersSettings; m_iDSVideoRendererType = s.iDSVideoRendererType; m_iRMVideoRendererType = s.iRMVideoRendererType; m_iQTVideoRendererType = s.iQTVideoRendererType; m_APSurfaceUsageCtrl.AddString(ResStr(IDS_PPAGE_OUTPUT_SURF_OFFSCREEN)); m_APSurfaceUsageCtrl.AddString(ResStr(IDS_PPAGE_OUTPUT_SURF_2D)); m_APSurfaceUsageCtrl.AddString(ResStr(IDS_PPAGE_OUTPUT_SURF_3D)); CorrectComboListWidth(m_APSurfaceUsageCtrl); m_iAPSurfaceUsage = r.iAPSurfaceUsage; m_DX9ResizerCtrl.AddString(ResStr(IDS_PPAGE_OUTPUT_RESIZE_NN)); m_DX9ResizerCtrl.AddString(ResStr(IDS_PPAGE_OUTPUT_RESIZER_BILIN)); m_DX9ResizerCtrl.AddString(ResStr(IDS_PPAGE_OUTPUT_RESIZER_BIL_PS)); m_DX9ResizerCtrl.AddString(ResStr(IDS_PPAGE_OUTPUT_RESIZER_BICUB1)); m_DX9ResizerCtrl.AddString(ResStr(IDS_PPAGE_OUTPUT_RESIZER_BICUB2)); m_DX9ResizerCtrl.AddString(ResStr(IDS_PPAGE_OUTPUT_RESIZER_BICUB3)); m_iDX9Resizer = r.iDX9Resizer; m_fVMR9MixerMode = r.fVMR9MixerMode; m_fVMR9MixerYUV = r.fVMR9MixerYUV; m_fVMR9AlterativeVSync = r.m_AdvRendSets.bVMR9AlterativeVSync; m_fD3DFullscreen = s.fD3DFullscreen; int EVRBuffers[] = { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30, 35, 40, 45, 50, 55, 60 }; CString EVRBuffer; for (size_t i = 0; i < _countof(EVRBuffers); i++) { EVRBuffer.Format(_T("%d"), EVRBuffers[i]); m_EVRBuffersCtrl.AddString(EVRBuffer); } m_iEvrBuffers.Format(_T("%d"), r.iEvrBuffers); m_iAudioRendererTypeCtrl.SetRedraw(FALSE); m_fResetDevice = s.m_RenderersSettings.fResetDevice; m_AudioRendererDisplayNames.Add(_T("")); m_iAudioRendererTypeCtrl.AddString(_T("1: ") + ResStr(IDS_PPAGE_OUTPUT_SYS_DEF)); m_iAudioRendererType = 0; int i = 2; CString Cbstr; BeginEnumSysDev(CLSID_AudioRendererCategory, pMoniker) { CComHeapPtr<OLECHAR> olestr; if (FAILED(pMoniker->GetDisplayName(0, 0, &olestr))) { continue; } CStringW str(olestr); m_AudioRendererDisplayNames.Add(CString(str)); CComPtr<IPropertyBag> pPB; if (SUCCEEDED(pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPB)))) { CComVariant var; if (SUCCEEDED(pPB->Read(_T("FriendlyName"), &var, nullptr))) { CString fstr(var.bstrVal); var.Clear(); if (SUCCEEDED(pPB->Read(_T("FilterData"), &var, nullptr))) { BSTR* pbstr; if (SUCCEEDED(SafeArrayAccessData(var.parray, (void**)&pbstr))) { fstr.Format(_T("%s (%08x)"), CString(fstr), *((DWORD*)pbstr + 1)); SafeArrayUnaccessData(var.parray); } } Cbstr.Format(_T("%d: %s"), i, fstr); } } else { Cbstr.Format(_T("%d: %s"), i, CString(str)); } m_iAudioRendererTypeCtrl.AddString(Cbstr); if (s.strAudioRendererDisplayName == str && m_iAudioRendererType == 0) { m_iAudioRendererType = m_iAudioRendererTypeCtrl.GetCount() - 1; } i++; }
HRESULT cDxCapture::GetInterfaces(void) { HRESULT hr; // Create the filter graph hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGraph); if (FAILED(hr)) return hr; // Create the capture graph builder hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **)&m_pCapture); if (FAILED(hr)) return hr; // Create the Sample Grabber filter. hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pGrabberF)); if (FAILED(hr)) return hr; hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pNullF)); if (FAILED(hr)) return hr; // Obtain interfaces for media control and Video Window hr = m_pGraph->QueryInterface(IID_IMediaControl, (LPVOID *)&m_pMC); if (FAILED(hr)) return hr; hr = m_pGraph->QueryInterface(IID_IVideoWindow, (LPVOID *)&m_pVW); if (FAILED(hr)) return hr; hr = m_pGraph->QueryInterface(IID_IMediaEvent, (LPVOID *)&m_pME); if (FAILED(hr)) return hr; hr = m_pGraph->AddFilter(m_pGrabberF, L"Sample Grabber"); if (FAILED(hr)) return hr; hr = m_pGrabberF->QueryInterface(IID_PPV_ARGS(&m_pGrabber)); if (FAILED(hr)) return hr; // Set the window handle used to process graph events // hr = m_pME->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0); AM_MEDIA_TYPE mt; ZeroMemory(&mt, sizeof(mt)); mt.majortype = MEDIATYPE_Video; //mt.subtype = MEDIASUBTYPE_RGB8; mt.subtype = MEDIASUBTYPE_RGB24; hr = m_pGrabber->SetMediaType(&mt); if (FAILED(hr)) return hr; return hr; }
// Load the rendering pipeline dependencies. void D3D12Bundles::LoadPipeline() { #if defined(_DEBUG) // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } else { ComPtr<IDXGIAdapter1> hardwareAdapter; GetHardwareAdapter(factory.Get(), &hardwareAdapter); ThrowIfFailed(D3D12CreateDevice( hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); NAME_D3D12_OBJECT(m_commandQueue); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.Width = m_width; swapChainDesc.Height = m_height; swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.SampleDesc.Count = 1; ComPtr<IDXGISwapChain1> swapChain; ThrowIfFailed(factory->CreateSwapChainForCoreWindow( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. reinterpret_cast<IUnknown*>(Windows::UI::Core::CoreWindow::GetForCurrentThread()), &swapChainDesc, nullptr, &swapChain )); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); // Describe and create a depth stencil view (DSV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {}; dsvHeapDesc.NumDescriptors = 1; dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&m_dsvHeap))); // Describe and create a shader resource view (SRV) and constant // buffer view (CBV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC cbvSrvHeapDesc = {}; cbvSrvHeapDesc.NumDescriptors = FrameCount * CityRowCount * CityColumnCount // FrameCount frames * CityRowCount * CityColumnCount. + 1; // + 1 for the SRV. cbvSrvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; cbvSrvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&cbvSrvHeapDesc, IID_PPV_ARGS(&m_cbvSrvHeap))); NAME_D3D12_OBJECT(m_cbvSrvHeap); // Describe and create a sampler descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC samplerHeapDesc = {}; samplerHeapDesc.NumDescriptors = 1; samplerHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; samplerHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&samplerHeapDesc, IID_PPV_ARGS(&m_samplerHeap))); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); m_cbvSrvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator))); }
CBrowseFolder::retVal CBrowseFolder::Show(HWND parent, CString& path, const CString& sDefaultPath /* = CString() */) { retVal ret = OK; //assume OK m_sDefaultPath = sDefaultPath; if (m_sDefaultPath.IsEmpty() && !path.IsEmpty()) { while (!PathFileExists(path) && !path.IsEmpty()) { CString p = path.Left(path.ReverseFind('\\')); if ((p.GetLength() == 2)&&(p[1] == ':')) { p += L"\\"; if (p.Compare(path) == 0) p.Empty(); } if (p.GetLength() < 2) p.Empty(); path = p; } // if the result path already contains a path, use that as the default path m_sDefaultPath = path; } HRESULT hr; // Create a new common open file dialog IFileOpenDialog* pfd = NULL; hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd)); if (SUCCEEDED(hr)) { // Set the dialog as a folder picker DWORD dwOptions; if (SUCCEEDED(hr = pfd->GetOptions(&dwOptions))) { hr = pfd->SetOptions(dwOptions | FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST); } // Set a title if (SUCCEEDED(hr)) { TCHAR * nl = wcschr(m_title, '\n'); if (nl) *nl = 0; pfd->SetTitle(m_title); } // set the default folder if (SUCCEEDED(hr)) { IShellItem *psiDefault = 0; hr = SHCreateItemFromParsingName(m_sDefaultPath, NULL, IID_PPV_ARGS(&psiDefault)); if (SUCCEEDED(hr)) { hr = pfd->SetFolder(psiDefault); psiDefault->Release(); } } if (m_CheckText[0] != 0) { IFileDialogCustomize* pfdCustomize = 0; hr = pfd->QueryInterface(IID_PPV_ARGS(&pfdCustomize)); if (SUCCEEDED(hr)) { pfdCustomize->StartVisualGroup(100, L""); pfdCustomize->AddCheckButton(101, m_CheckText, FALSE); if (m_CheckText2[0] != 0) { pfdCustomize->AddCheckButton(102, m_CheckText2, FALSE); } pfdCustomize->EndVisualGroup(); pfdCustomize->Release(); } } // Show the open file dialog if (SUCCEEDED(hr) && SUCCEEDED(hr = pfd->Show(parent))) { // Get the selection from the user IShellItem* psiResult = NULL; hr = pfd->GetResult(&psiResult); if (SUCCEEDED(hr)) { PWSTR pszPath = NULL; hr = psiResult->GetDisplayName(SIGDN_FILESYSPATH, &pszPath); if (SUCCEEDED(hr)) { path = pszPath; CoTaskMemFree(pszPath); } psiResult->Release(); IFileDialogCustomize* pfdCustomize = 0; hr = pfd->QueryInterface(IID_PPV_ARGS(&pfdCustomize)); if (SUCCEEDED(hr)) { pfdCustomize->GetCheckButtonState(101, &m_bCheck); pfdCustomize->GetCheckButtonState(102, &m_bCheck2); pfdCustomize->Release(); } } else ret = CANCEL; } else ret = CANCEL; pfd->Release(); } else { BROWSEINFO browseInfo = {}; browseInfo.hwndOwner = parent; browseInfo.pidlRoot = m_root; browseInfo.pszDisplayName = m_displayName; browseInfo.lpszTitle = m_title; browseInfo.ulFlags = m_style; browseInfo.lParam = (LPARAM)this; browseInfo.lpfn = BrowseCallBackProc; PCIDLIST_ABSOLUTE itemIDList = SHBrowseForFolder(&browseInfo); //is the dialog canceled? if (!itemIDList) ret = CANCEL; if (ret != CANCEL) { if (!SHGetPathFromIDList(itemIDList, path.GetBuffer(MAX_PATH))) // MAX_PATH ok. Explorer can't handle paths longer than MAX_PATH. ret = NOPATH; path.ReleaseBuffer(); CoTaskMemFree((LPVOID)itemIDList); } } return ret; }