diff --git a/Kits/ATGTK/ControllerHelp.cpp b/Kits/ATGTK/ControllerHelp.cpp index 485868e..0883782 100644 --- a/Kits/ATGTK/ControllerHelp.cpp +++ b/Kits/ATGTK/ControllerHelp.cpp @@ -974,6 +974,8 @@ void ATG::Help::RestoreDevice(ID3D11DeviceContext* context) ); } + const DDS_LOADER_FLAGS loadFlags = m_linearColors ? DDS_LOADER_FORCE_SRGB : DDS_LOADER_DEFAULT; + #if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) wchar_t buff[MAX_PATH]; DX::FindMediaFile(buff, MAX_PATH, L"SegoeUI_18.spritefont"); @@ -986,21 +988,21 @@ void ATG::Help::RestoreDevice(ID3D11DeviceContext* context) m_spriteFonts[SEGOE_UI_36PT] = std::make_unique(device.Get(), buff); DX::FindMediaFile(buff, MAX_PATH, L"callout_circle.dds"); - DX::ThrowIfFailed(CreateDDSTextureFromFileEx(device.Get(), buff, 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, m_linearColors, nullptr, m_circleTex.ReleaseAndGetAddressOf())); + DX::ThrowIfFailed(CreateDDSTextureFromFileEx(device.Get(), buff, 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, loadFlags, nullptr, m_circleTex.ReleaseAndGetAddressOf())); DX::FindMediaFile(buff, MAX_PATH, L"gamepad.dds"); - DX::ThrowIfFailed(CreateDDSTextureFromFileEx(device.Get(), buff, 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, m_linearColors, nullptr, m_gamepadTex.ReleaseAndGetAddressOf())); + DX::ThrowIfFailed(CreateDDSTextureFromFileEx(device.Get(), buff, 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, loadFlags, nullptr, m_gamepadTex.ReleaseAndGetAddressOf())); DX::FindMediaFile(buff, MAX_PATH, L"ATGSampleBackground.DDS"); - DX::ThrowIfFailed(CreateDDSTextureFromFileEx(device.Get(), buff, 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, m_linearColors, nullptr, m_backgroundTex.ReleaseAndGetAddressOf())); + DX::ThrowIfFailed(CreateDDSTextureFromFileEx(device.Get(), buff, 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, loadFlags, nullptr, m_backgroundTex.ReleaseAndGetAddressOf())); #else m_spriteFonts[SEGOE_UI_18PT] = std::make_unique(device.Get(), L"SegoeUI_18.spritefont"); m_spriteFonts[SEGOE_UI_22PT] = std::make_unique(device.Get(), L"SegoeUI_22.spritefont"); m_spriteFonts[SEGOE_UI_36PT] = std::make_unique(device.Get(), L"SegoeUI_36.spritefont"); - DX::ThrowIfFailed(CreateDDSTextureFromFileEx(device.Get(), L"callout_circle.dds", 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, m_linearColors, nullptr, m_circleTex.ReleaseAndGetAddressOf())); - DX::ThrowIfFailed(CreateDDSTextureFromFileEx(device.Get(), L"gamepad.dds", 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, m_linearColors, nullptr, m_gamepadTex.ReleaseAndGetAddressOf())); - DX::ThrowIfFailed(CreateDDSTextureFromFileEx(device.Get(), L"ATGSampleBackground.DDS", 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, m_linearColors, nullptr, m_backgroundTex.ReleaseAndGetAddressOf())); + DX::ThrowIfFailed(CreateDDSTextureFromFileEx(device.Get(), L"callout_circle.dds", 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, loadFlags, nullptr, m_circleTex.ReleaseAndGetAddressOf())); + DX::ThrowIfFailed(CreateDDSTextureFromFileEx(device.Get(), L"gamepad.dds", 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, loadFlags, nullptr, m_gamepadTex.ReleaseAndGetAddressOf())); + DX::ThrowIfFailed(CreateDDSTextureFromFileEx(device.Get(), L"ATGSampleBackground.DDS", 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, loadFlags, nullptr, m_backgroundTex.ReleaseAndGetAddressOf())); #endif } #endif diff --git a/Kits/ATGTK/FrontPanel/FrontPanelDisplay.cpp b/Kits/ATGTK/FrontPanel/FrontPanelDisplay.cpp index a09e5c8..cbb9fd6 100644 --- a/Kits/ATGTK/FrontPanel/FrontPanelDisplay.cpp +++ b/Kits/ATGTK/FrontPanel/FrontPanelDisplay.cpp @@ -69,18 +69,17 @@ namespace namespace DirectX { - namespace Internal + inline namespace DX12 { - // Reuse the WIC factory function from the DirectX Tool Kit. For implementation details, see WICTextureLoader.cpp -#if defined(__d3d12_x_h__) || defined(__XBOX_D3D12_X__) - extern IWICImagingFactory2* GetWIC(); -#else - extern IWICImagingFactory* GetWIC(); -#endif + namespace Internal + { + // Reuse the WIC factory function from the DirectX Tool Kit. For implementation details, see WICTextureLoader.cpp + extern IWICImagingFactory2* GetWIC(); + } } } -using namespace DirectX::Internal; +using namespace DirectX::DX12::Internal; // -------------------------------------------------------------------------------- // FrontPanelDisplay methods diff --git a/Kits/ATGTK/Processor.cpp b/Kits/ATGTK/Processor.cpp index 9ebee2e..ea9e640 100644 --- a/Kits/ATGTK/Processor.cpp +++ b/Kits/ATGTK/Processor.cpp @@ -14,7 +14,6 @@ #include #undef max #undef min -#include "intrin.h" #if defined(_GAMING_XBOX) #include @@ -41,7 +40,7 @@ namespace std::wstring g_processorName; // The general processor name. This can be changed by the user to allow easier usage in their code std::wstring g_trueProcessorName; // The actual name of the processor as returned by the OS uint64_t g_processMask = 0; // In general all the cores that exist on the processor, when >64 this will be bound to the group the process is assigned to - std::vector g_numLogicalCores; // How many logical cores exist, if not hyperthreaded == number of physical cores + std::vector g_numLogicalCores; // How many logical cores exist, if SMT is not supported == number of physical cores std::vector g_availableCoresMask; // Which cores are actually available to the caller, for example ERA does not allow the 8th core to be used, index is groupID #if !defined(_XBOX_ONE) // we don't use this on ERA because GetLogicalProcessorInfoEx and GetLogicalProcessorInformation is not supported @@ -65,7 +64,7 @@ namespace SYSTEM_INFO g_systemInfo; // Cached copy of data from GetSystemInfo std::vector g_topLevelCacheMask; // For each top level cache the mask of cores that share id. This tends to be processors that have several internal clusters, for example Durango has two clusters - std::map>> g_physicalCores; // For each physical core a mask of the logical cores that map to that physical core and a flag for whether it's hyperthreaded + std::map>> g_physicalCores; // For each physical core a mask of the logical cores that map to that physical core and a flag for whether it has support for SMT std::vector g_caches; // A list of each cache present on the processor, L1, L2, L3, Instruction, Data, and Trace (haven't seen this on any processor yet) double g_rdtscpFrequencySeconds; // The frequency in seconds of the __rdtscp, measured automatically at startup @@ -315,15 +314,32 @@ void ATG::GetCacheInformation(const UniqueProcessorMask& coreMask, std::vector (((CPUInfo[0] & 0xf00) >> 8) + ((CPUInfo[0] & 0x0ff00000) >> 20)); +} + bool ATG::SetupProcessorData() { + if (g_trueProcessorName.size()) + return true; + #if !defined(_XBOX_ONE) && !defined(_GAMING_XBOX) // Xbox doesn't have this registry entry g_osProcessorInfo.bufferSize = 0; g_osProcessorInfo.rawData = nullptr; - wchar_t processorName[256] = {}; - DWORD dataSize = sizeof(wchar_t) * 256; - RegGetValueW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", L"ProcessorNameString", RRF_RT_REG_SZ, nullptr, processorName, &dataSize); - g_trueProcessorName = processorName; + { + wchar_t processorName[256]; + DWORD dataSize = sizeof(wchar_t) * 256; + RegGetValueW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", L"ProcessorNameString", RRF_RT_REG_SZ, nullptr, processorName, &dataSize); + g_trueProcessorName = processorName; + } #elif defined(_GAMING_XBOX) XSystemDeviceType info; info = XSystemGetDeviceType(); @@ -410,7 +426,7 @@ bool ATG::SetupProcessorData() ParseOSProcessorInfo(); #if defined(_GAMING_XBOX) - if (ATG::IsHyperThreaded()) + if (ATG::IsSMTSupported()) g_trueProcessorName += L"_SMT"; g_processorName = g_trueProcessorName; #endif @@ -500,7 +516,7 @@ void ATG::LogProcessorInfo(const std::wstring& logName) swprintf_s(buffer, 256, L"%s_procInfo", g_trueProcessorName.c_str()); fileName = buffer; } - ATG::FileLogger procLog(fileName, false); + ATG::FileLogger procLog(fileName, false, false, false, true, true); #if !defined(_GAMING_XBOX) wchar_t buffer[256]; @@ -531,7 +547,7 @@ void ATG::LogProcessorInfo(const std::wstring& logName) case RelationProcessorCore: procLog.Log(L"Processor Core"); if (procInfo->Processor.Flags == LTP_PC_SMT) - procLog.Log(L" Core is hyper threaded"); + procLog.Log(L" Core supports SMT"); if (procInfo->Processor.EfficiencyClass != 0) procLog.Log(L" Core efficiency class is set"); for (uint32_t i = 0; i < procInfo->Processor.GroupCount; i++) @@ -658,7 +674,7 @@ void ATG::LogProcessorInfo(const std::wstring& logName) case RelationProcessorCore: procLog.Log(L"Processor Core"); if (procInfo->ProcessorCore.Flags == 1) - procLog.Log(L" Core is hyper threaded"); + procLog.Log(L" Core supports SMT"); swprintf(buffer, 256, L" CoreMask - %016I64x", procInfo->ProcessorMask); procLog.Log(buffer); break; @@ -691,7 +707,7 @@ void ATG::LogCoreTests(const std::wstring& suffix, const std::wstring& logName) swprintf_s(buffer, 256, L"%s_coreTests_%s", g_trueProcessorName.c_str(), suffix.c_str()); fileName = buffer; } - ATG::FileLogger testLog(fileName, false); + ATG::FileLogger testLog(fileName, false, false, false, true, true); size_t numTests = g_representativeCoreTests.size(); for (size_t i = 0; i < numTests; i++) { @@ -776,7 +792,7 @@ namespace testNames.push_back(L"all_cores"); // one logical per physical - if (ATG::IsHyperThreaded()) + if (ATG::IsSMTSupported()) { uint64_t oneLogicalMask = 0; for (const auto& iter : cpuSets) @@ -814,7 +830,7 @@ namespace } // single physical core, one per cluster - if (minLowCacheCores > 1) // this means hyperthreaded + if (minLowCacheCores > 1) // this means SMT is supported { for (const auto& cluster : cpuSets) { @@ -935,7 +951,7 @@ namespace } } - // cross cluster tests, pick one physical core even if hyperthreaded + // cross cluster tests, pick one physical core even if SMT is supported { for (const auto& outerCluster : cpuSets) { @@ -976,21 +992,21 @@ namespace testNames.clear(); constexpr uint32_t s_maxSingleCores = 4u; - bool hyperThreaded = false; + bool smtSupported = false; uint64_t allCoresMask(0); wchar_t tempBuffer[256]; for (const auto& iter : g_physicalCores[groupID]) { allCoresMask |= iter.second; if (iter.first) - hyperThreaded = true; + smtSupported = true; } coreTests.push_back(allCoresMask); // do everything testNames.push_back(L"all_cores"); // physical cores { const uint32_t numSingle = std::min(ATG::GetNumPhysicalCores(groupID), s_maxSingleCores); - const uint32_t coreDelta = std::max(hyperThreaded ? 2U : 1U, static_cast ((((float)ATG::GetTotalNumCores(groupID)) / numSingle) + 0.5f)); // assume hyperthreaded are only 2 cores per physical + const uint32_t coreDelta = std::max(smtSupported ? 2U : 1U, static_cast ((((float)ATG::GetTotalNumCores(groupID)) / numSingle) + 0.5f)); // assume SMT supported are only 2 cores per physical uint64_t curMask = 0; for (uint32_t i = 0; i < numSingle; i++, curMask += coreDelta) { @@ -999,10 +1015,10 @@ namespace testNames.push_back(tempBuffer); } } - if (hyperThreaded) + if (smtSupported) { const uint32_t numSingle = std::min(ATG::GetNumPhysicalCores(groupID), s_maxSingleCores); - const uint32_t coreDelta = std::max(2, ATG::GetTotalNumCores(groupID) / numSingle); // assume hyperthreaded are only 2 cores per physical. Code below will set the mask correctly + const uint32_t coreDelta = std::max(2, ATG::GetTotalNumCores(groupID) / numSingle); // assume SMT supported are only 2 cores per physical. Code below will set the mask correctly uint64_t curMask = 0; for (uint32_t i = 0; i < numSingle; i++, curMask += coreDelta) { @@ -1015,7 +1031,6 @@ namespace if (g_dieMask.size() > 1) // numa nodes will show up here { // all cores in a cluster - uint32_t curCluster = 0; for (const auto& iter : g_dieMask) { if (iter.second.groupID != groupID) @@ -1023,11 +1038,9 @@ namespace coreTests.push_back(iter.second.coreMask); swprintf_s(tempBuffer, 256, L"full_cluster_0x%llx", iter.second.coreMask); testNames.push_back(tempBuffer); - curCluster++; } // two cores in a cluster - curCluster = 0; for (const auto& iter : g_dieMask) { if (iter.second.groupID != groupID) @@ -1040,14 +1053,12 @@ namespace swprintf_s(tempBuffer, 256, L"within_cluster_physical_0x%llx", (1ULL << lowBitIndex) | (1ULL << highBitIndex)); testNames.push_back(tempBuffer); - if (hyperThreaded) + if (smtSupported) { coreTests.push_back(ATG::GetLogicalProcessorMask(ATG::UniqueProcessorMask(1ULL << lowBitIndex, groupID)) | ATG::GetLogicalProcessorMask(ATG::UniqueProcessorMask(1ULL << highBitIndex, groupID))); - swprintf_s(tempBuffer, 256, L"within_cluster_hyper_0x%llx", ATG::GetLogicalProcessorMask(ATG::UniqueProcessorMask(1ULL << lowBitIndex, groupID)) | ATG::GetLogicalProcessorMask(ATG::UniqueProcessorMask(1ULL << highBitIndex, groupID))); + swprintf_s(tempBuffer, 256, L"within_cluster_SMT_0x%llx", ATG::GetLogicalProcessorMask(ATG::UniqueProcessorMask(1ULL << lowBitIndex, groupID)) | ATG::GetLogicalProcessorMask(ATG::UniqueProcessorMask(1ULL << highBitIndex, groupID))); testNames.push_back(tempBuffer); } - - curCluster++; } // one physical on all combinations of 2 clusters @@ -1073,7 +1084,7 @@ namespace _BitScanForward64(&outerBitIndex, outer->second.coreMask); _BitScanForward64(&innerBitIndex, inner->second.coreMask); - if (hyperThreaded) + if (smtSupported) { coreTests.push_back(ATG::GetLogicalProcessorMask(ATG::UniqueProcessorMask(1ULL << outerBitIndex, groupID)) | ATG::GetLogicalProcessorMask(ATG::UniqueProcessorMask(1ULL << innerBitIndex, groupID))); swprintf_s(tempBuffer, 256, L"cross_cluster_logical_0x%llx", ATG::GetLogicalProcessorMask(ATG::UniqueProcessorMask(1ULL << outerBitIndex, groupID)) | ATG::GetLogicalProcessorMask(ATG::UniqueProcessorMask(1ULL << innerBitIndex, groupID))); @@ -1091,7 +1102,7 @@ namespace // half the cores in a single const uint32_t halfLogical = ATG::GetNumLogicalCores(groupID) / 2; uint64_t lowMask(0), highMask(0); - for (uint32_t i = 0; i < halfLogical; i += hyperThreaded ? 2 : 1) + for (uint32_t i = 0; i < halfLogical; i += smtSupported ? 2 : 1) { lowMask |= ATG::GetLogicalProcessorMask(ATG::UniqueProcessorMask(1ULL << i, groupID)); highMask |= ATG::GetLogicalProcessorMask(ATG::UniqueProcessorMask(1ULL << (halfLogical + i), groupID)); @@ -1105,7 +1116,7 @@ namespace testNames.push_back(tempBuffer); // two physical cores - if (hyperThreaded && (ATG::GetNumPhysicalCores(groupID) >= 4)) // just assume 2 cores in a hyperthread and at least 4 physical cores + if (smtSupported && (ATG::GetNumPhysicalCores(groupID) >= 4)) // just assume 2 cores in a SMT supported and at least 4 physical cores { coreTests.push_back(0x05); swprintf_s(tempBuffer, 256, L"first two physical 0x05"); @@ -1115,8 +1126,8 @@ namespace swprintf_s(tempBuffer, 256, L"second two physical 0xA0"); testNames.push_back(tempBuffer); } - // handle 2 physical hyperthreaded cores - if (hyperThreaded && (ATG::GetNumPhysicalCores(groupID) == 2)) + // handle 2 physical SMT cores + if (smtSupported && (ATG::GetNumPhysicalCores(groupID) == 2)) { coreTests.push_back(0x05); swprintf_s(tempBuffer, 256, L"Two physical_0x05"); @@ -1309,7 +1320,6 @@ namespace g_numLogicalCores.resize(groupCount, 0); g_availableCoresMask.resize(groupCount, 0); - uint32_t entries = 0; data = g_osProcessorInfo.rawData; dataLeft = g_osProcessorInfo.bufferSize; while (dataLeft) @@ -1367,7 +1377,6 @@ namespace } dataLeft -= procInfo->Size; data = data + procInfo->Size; - entries++; } #endif diff --git a/Kits/ATGTK/Processor.h b/Kits/ATGTK/Processor.h index fee6ae2..00c73f6 100644 --- a/Kits/ATGTK/Processor.h +++ b/Kits/ATGTK/Processor.h @@ -21,6 +21,8 @@ namespace ATG using ProcessorGroupID = uint16_t; using ProcessorNumaNodeID = uint32_t; + constexpr uint32_t JAGUAR_PROCESSOR_FAMILY = 0x16; + constexpr uint32_t ZEN2_PROCESSOR_FAMILY = 0x17; struct UniqueProcessorMask { @@ -86,7 +88,7 @@ namespace ATG uint32_t GetTotalNumCores(ProcessorGroupID groupID = 0); uint64_t GetAvailableCoresMask(ProcessorGroupID groupID = 0); - inline bool IsHyperThreaded(ProcessorGroupID groupID = 0) { return GetNumPhysicalCores(groupID) < GetNumLogicalCores(groupID); } + inline bool IsSMTSupported(ProcessorGroupID groupID = 0) { return GetNumPhysicalCores(groupID) < GetNumLogicalCores(groupID); } double GetRDTSCPFrequencySeconds(); double GetRDTSCPFrequencyMilliseconds(); double GetRDTSCPFrequencyMicroseconds(); @@ -94,6 +96,7 @@ namespace ATG const std::wstring& GetProcessorName(); // will be the override value which is initially the true name const std::wstring& GetTrueProcessorName(); void SetProcessorName(const std::wstring& overrideName); + uint32_t GetProcessorFamily(); uint64_t GetLogicalProcessorMask(uint64_t coreMask); // adjusts the mask to cover all logical processors diff --git a/Kits/ATGTK/RDTSCPStopWatch.h b/Kits/ATGTK/RDTSCPStopWatch.h index 80edfa0..d223ef5 100644 --- a/Kits/ATGTK/RDTSCPStopWatch.h +++ b/Kits/ATGTK/RDTSCPStopWatch.h @@ -10,103 +10,109 @@ #include #include -#include "intrin.h" +#include namespace ATG { - double CalcRDTSCPFrequency(); - extern double s_rdtscpFrequencySecs; - extern double s_rdtscpFrequencyMS; - extern double s_rdtscpFrequencyUS; + double CalcRDTSCPFrequency(); + extern double s_rdtscpFrequencySecs; + extern double s_rdtscpFrequencyMS; + extern double s_rdtscpFrequencyUS; + extern double s_rdtscpFrequencyNS; - class RDTSCPStopWatch - { - private: - uint64_t m_startTimeRaw; - uint64_t m_stopTimeRaw; - bool m_running; + class RDTSCPStopWatch + { + private: + uint64_t m_startTimeRaw; + uint64_t m_stopTimeRaw; + bool m_running; - public: + public: - RDTSCPStopWatch() :m_startTimeRaw(0), m_stopTimeRaw(0), m_running(false) {} - void Start() - { - assert(!m_running); - m_running = true; - m_stopTimeRaw = 0; - uint32_t tempAux; - m_startTimeRaw = __rdtscp(&tempAux); - } - double Stop() - { - assert(m_running); - uint32_t tempAux; - m_stopTimeRaw = __rdtscp(&tempAux); - m_running = false; - return GetTotalSeconds(); - } + RDTSCPStopWatch() :m_startTimeRaw(0), m_stopTimeRaw(0), m_running(false) {} - void Reset() - { - m_startTimeRaw = 0; - m_stopTimeRaw = 0; - } + bool IsRunning() const noexcept { return m_running; } + void Start() + { + assert(!m_running); + m_running = true; + m_stopTimeRaw = 0; + uint32_t tempAux; + m_startTimeRaw = __rdtscp(&tempAux); + } + double Stop() + { + assert(m_running); + uint32_t tempAux; + m_stopTimeRaw = __rdtscp(&tempAux); + m_running = false; + return GetTotalSeconds(); + } - static double GetFrequencyMilliseconds() { return s_rdtscpFrequencyMS; } + void Reset() + { + uint32_t tempAux; + m_startTimeRaw = __rdtscp(&tempAux); + m_stopTimeRaw = 0; + } - double GetCurrentSeconds() const - { - assert(m_running); - uint32_t tempAux; - uint64_t temp; - temp = __rdtscp(&tempAux); - return static_cast(temp - m_startTimeRaw) / s_rdtscpFrequencySecs; - } - double GetCurrentMilliseconds() const - { - assert(m_running); - uint32_t tempAux; - uint64_t temp; - temp = __rdtscp(&tempAux); - return static_cast(temp - m_startTimeRaw) / s_rdtscpFrequencyMS; - } - double GetCurrentMicroseconds() const - { - assert(m_running); - uint32_t tempAux; - uint64_t temp; - temp = __rdtscp(&tempAux); - return static_cast(temp - m_startTimeRaw) / s_rdtscpFrequencyUS; - } - uint64_t GetCurrentRaw() const - { - assert(m_running); - uint32_t tempAux; - uint64_t temp; - temp = __rdtscp(&tempAux); - return temp - m_startTimeRaw; - } + static double GetFrequencyMilliseconds() { return s_rdtscpFrequencyMS; } + static double GetFrequencyMicroseconds() { return s_rdtscpFrequencyUS; } + static double GetFrequencyNanoseconds() { return s_rdtscpFrequencyNS; } - double GetTotalSeconds() const - { - assert(!m_running); - return static_cast(m_stopTimeRaw - m_startTimeRaw) / s_rdtscpFrequencySecs; - } - double GetTotalMilliseconds() const - { - assert(!m_running); - return static_cast(m_stopTimeRaw - m_startTimeRaw) / s_rdtscpFrequencyMS; - } - double GetTotalMicroseconds() const - { - assert(!m_running); - return static_cast(m_stopTimeRaw - m_startTimeRaw) / s_rdtscpFrequencyUS; - } + double GetCurrentSeconds() const + { + assert(m_running); + uint32_t tempAux; + uint64_t temp; + temp = __rdtscp(&tempAux); + return static_cast(temp - m_startTimeRaw) / s_rdtscpFrequencySecs; + } + double GetCurrentMilliseconds() const + { + assert(m_running); + uint32_t tempAux; + uint64_t temp; + temp = __rdtscp(&tempAux); + return static_cast(temp - m_startTimeRaw) / s_rdtscpFrequencyMS; + } + double GetCurrentMicroseconds() const + { + assert(m_running); + uint32_t tempAux; + uint64_t temp; + temp = __rdtscp(&tempAux); + return static_cast(temp - m_startTimeRaw) / s_rdtscpFrequencyUS; + } + uint64_t GetCurrentRaw() const + { + assert(m_running); + uint32_t tempAux; + uint64_t temp; + temp = __rdtscp(&tempAux); + return temp - m_startTimeRaw; + } - uint64_t GetTotalRaw() const - { - assert(!m_running); - return m_stopTimeRaw - m_startTimeRaw; - } - }; + double GetTotalSeconds() const + { + assert(!m_running); + return static_cast(m_stopTimeRaw - m_startTimeRaw) / s_rdtscpFrequencySecs; + } + double GetTotalMilliseconds() const + { + assert(!m_running); + return static_cast(m_stopTimeRaw - m_startTimeRaw) / s_rdtscpFrequencyMS; + } + double GetTotalMicroseconds() const + { + assert(!m_running); + return static_cast(m_stopTimeRaw - m_startTimeRaw) / s_rdtscpFrequencyUS; + } + + uint64_t GetTotalRaw() const + { + assert(!m_running); + return m_stopTimeRaw - m_startTimeRaw; + } + }; } diff --git a/Kits/ATGTK/RDTSCPStopwatch.cpp b/Kits/ATGTK/RDTSCPStopwatch.cpp index eceed3a..30c0146 100644 --- a/Kits/ATGTK/RDTSCPStopwatch.cpp +++ b/Kits/ATGTK/RDTSCPStopwatch.cpp @@ -15,6 +15,7 @@ namespace ATG double s_rdtscpFrequencySecs = CalcRDTSCPFrequency(); // force init at startup double s_rdtscpFrequencyMS; // CalcRDTSCPFrequency auto sets these double s_rdtscpFrequencyUS; // CalcRDTSCPFrequency auto sets these + double s_rdtscpFrequencyNS; // CalcRDTSCPFrequency auto sets these double CalcRDTSCPFrequency() { @@ -64,8 +65,9 @@ namespace ATG SetThreadPriority(GetCurrentThread(), currentPriority); s_rdtscpFrequencySecs = (rdtscFrequencyIdle + rdtscFrequencyLoad) / 2.0; // the numbers should be close to identical so just average - s_rdtscpFrequencyMS = s_rdtscpFrequencySecs / 1000; - s_rdtscpFrequencyUS = s_rdtscpFrequencySecs / 1000000; + s_rdtscpFrequencyMS = s_rdtscpFrequencySecs / 1000.0; + s_rdtscpFrequencyUS = s_rdtscpFrequencySecs / 1000000.0; + s_rdtscpFrequencyNS = s_rdtscpFrequencySecs / 1000000000.0; return s_rdtscpFrequencySecs; } diff --git a/Kits/ATGTK/Random.h b/Kits/ATGTK/Random.h index 6e6140d..6c9e5e5 100644 --- a/Kits/ATGTK/Random.h +++ b/Kits/ATGTK/Random.h @@ -11,26 +11,28 @@ namespace ATG { - template - randomSize GetRandomValue(randomSize range) - { - static std::random_device randomDevice; - static std::mt19937_64 randomEngine(randomDevice()); + template + randomSize GetRandomValue(randomSize range) + { + if (range == 0) + return range; + static std::random_device randomDevice; + static std::mt19937_64 randomEngine(randomDevice()); - using distribution = typename std::conditional< std::is_floating_point_v, std::uniform_real_distribution, std::uniform_int_distribution>::type; - static distribution randomValue(0, std::numeric_limits::max()); + using distribution = typename std::conditional< std::is_floating_point_v, std::uniform_real_distribution, std::uniform_int_distribution>::type; + static distribution randomValue(0, std::numeric_limits::max()); - randomSize toret = randomValue(randomEngine); - if (std::is_floating_point_v) - { - toret /= std::numeric_limits::max(); - toret *= range; - } - else - { - randomSize temp = toret / range; - toret -= (temp * range); - } - return toret; - } + randomSize toret = randomValue(randomEngine); + if (std::is_floating_point_v) + { + toret /= std::numeric_limits::max(); + toret *= range; + } + else + { + randomSize temp = toret / range; + toret -= (temp * range); + } + return toret; + } } diff --git a/Kits/ATGTK/Texture.cpp b/Kits/ATGTK/Texture.cpp index d8361a9..23ddaa3 100644 --- a/Kits/ATGTK/Texture.cpp +++ b/Kits/ATGTK/Texture.cpp @@ -198,7 +198,7 @@ Texture::Texture(ID3D11Device* device, const wchar_t* fileName, bool forceSRGB) ThrowIfFailed( CreateDDSTextureFromFileEx( device, fileName, 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, - forceSRGB, + forceSRGB ? DDS_LOADER_FORCE_SRGB : DDS_LOADER_DEFAULT, resource.GetAddressOf(), resourceView.GetAddressOf(), &m_alphaMode) ); } diff --git a/Kits/ATGTK/UnicodeRendering/GlyphCache.h b/Kits/ATGTK/UnicodeRendering/GlyphCache.h index 82db9bd..f7a7b40 100644 --- a/Kits/ATGTK/UnicodeRendering/GlyphCache.h +++ b/Kits/ATGTK/UnicodeRendering/GlyphCache.h @@ -11,11 +11,9 @@ #include "ATGColors.h" -namespace DirectX { - class SpriteBatch; - class DescriptorHeap; - enum SpriteEffects : uint32_t; -} +#include "DescriptorHeap.h" +#include "SpriteBatch.h" + namespace ATG { diff --git a/Kits/ATGTK/UserLockable.h b/Kits/ATGTK/UserLockable.h index e12c039..740c54f 100644 --- a/Kits/ATGTK/UserLockable.h +++ b/Kits/ATGTK/UserLockable.h @@ -7,7 +7,6 @@ #pragma once -#include #include namespace ATG @@ -33,7 +32,7 @@ namespace ATG UserEventLockable(const UserEventLockable&) = delete; UserEventLockable& operator=(const UserEventLockable&) = delete; - UserEventLockable(bool initialState = true) : m_threadsWaiting(0), m_eventFlag(static_cast (initialState ? 1 : 0)) { } + UserEventLockable(bool initialState = true) noexcept : m_threadsWaiting(0), m_eventFlag(initialState ? 1 : 0u) { } UserEventLockable(UserEventLockable&& rhs) = default; ~UserEventLockable() { } @@ -143,7 +142,7 @@ namespace ATG UserSemaphoreLockable(UserSemaphoreLockable&& rhs) = delete; UserSemaphoreLockable& operator=(const UserSemaphoreLockable&&) = delete; - UserSemaphoreLockable(uint32_t intialValue) : m_threadsWaiting(0), m_semaphore(intialValue) { } + UserSemaphoreLockable(uint32_t intialValue) noexcept : m_threadsWaiting(0), m_semaphore(intialValue) { } ~UserSemaphoreLockable() { } void lock() @@ -173,6 +172,7 @@ namespace ATG const uint32_t newValue = currentValue - 1; // locking only reduces the count by 1 if (InterlockedCompareExchange(&m_semaphore, newValue, currentValue) == currentValue) return true; + _mm_pause(); } } @@ -185,6 +185,7 @@ namespace ATG const uint32_t newValue = currentValue + releaseCount; if (InterlockedCompareExchange(&m_semaphore, newValue, currentValue) == currentValue) break; + _mm_pause(); } if (m_threadsWaiting) // only call WakeByAddress if there is a high probability of a thread actually waiting. @@ -241,29 +242,100 @@ namespace ATG ////////////////////////////////////////////////////////////////////////// /// - /// Event object that attempts to stay at user level as much as possible - /// The object will only go to kernel mode if there is actually a thread waiting on the event - /// This allows for the maximum performance. + /// UserBarrier object that attempts to stay at user level as much as possible + /// The object will only go to kernel mode if requested and it's waiting for more threads to hit the barrier + /// The enterBarrier call can be set to pure spin to allow all waiting threads to exit as soon as possible + /// If threads spin care must be taken that no other threads are running on the same core to avoid extremely long waits + /// The threadOwner template parameter provides protection so only a single thread can call reset, the initial thread to enter the barrier + /// + ////////////////////////////////////////////////////////////////////////// + template + class UserBarrier + { + private: + std::atomic m_barrierValue; + uint64_t m_initialValue; + UserEventLockable m_blockEvent; + uint32_t m_threadOwnerID; + + public: + /// The UserBarrier cannot be copied + UserBarrier(const UserBarrier&) = delete; + UserBarrier& operator=(const UserBarrier&) = delete; + + UserBarrier(uint64_t initialValue = 1) noexcept : m_barrierValue(initialValue), m_initialValue(initialValue), m_blockEvent(false), m_threadOwnerID(0) { } + UserBarrier(UserBarrier&& rhs) = default; + ~UserBarrier() { } + + void clearOwner() { m_threadOwnerID = 0; } + + bool enterBarrier(bool block = false) + { + assert(m_barrierValue != 0); + if (threadOwner) + { + if (m_threadOwnerID == 0) + m_threadOwnerID = GetCurrentThreadId(); + } + uint64_t myValue = m_barrierValue.fetch_sub(1); + if (myValue == 1) + { + m_blockEvent.SetEvent(); + return true; + } + else if (block) + { + m_blockEvent.lock(); + } + else + { + while (m_barrierValue.load() != 0) { _mm_pause(); } + } + return false; + } + + bool reset() { return reset(m_initialValue); } + bool reset(uint64_t newValue) + { + if (threadOwner) + { + if (m_threadOwnerID != GetCurrentThreadId()) + { + if (InterlockedCompareExchange(&m_threadOwnerID, GetCurrentThreadId(), 0) != 0) + return false; + } + } + m_initialValue = newValue; + m_barrierValue = newValue; + m_blockEvent.SetEvent(); + m_blockEvent.ResetEvent(); + return true; + } + }; + + ////////////////////////////////////////////////////////////////////////// + /// + /// MonitorXMwaitXLockable object that attempts to stay at user level as much as possible + /// Spin lock implemented using the monitorx/mwaitx instructions + /// This class will stay in user-mode the entire time /// Interfaces follow the C++11 TimeLockable concept - /// The template parameter on manual reset is used to allow the compiler to optimize out the conditional /// ////////////////////////////////////////////////////////////////////////// #if !defined(__clang__) || defined (__MWAITX__) //NOTE: Clang explictly only includes this intrinsic if __MWAITX__ is defined and it needs to be defined in the pch file before the x86intrin.h is included #pragma warning (push) -#pragma warning (disable: 4324) +#pragma warning (disable: 4324) // structure was padded class alignas(64) MonitorXMwaitXLockable { private: uint32_t m_eventFlag; // the current event flag, interlocks are used on it for thread safety uint32_t m_owningThread; - char unusedForceSizeBlock[56]; // force size to be 64 bytes public: - /// The UserSemaphoreLockable cannot be copied + /// The MonitorXMwaitXLockable cannot be copied MonitorXMwaitXLockable(const MonitorXMwaitXLockable&) = delete; MonitorXMwaitXLockable& operator=(const MonitorXMwaitXLockable&) = delete; - MonitorXMwaitXLockable(bool initialState = false) : m_eventFlag(static_cast (initialState ? 1 : 0)), m_owningThread(0), unusedForceSizeBlock{ } { } + MonitorXMwaitXLockable(bool initialState = false) noexcept : m_eventFlag(initialState ? 1u : 0), m_owningThread(0) {} MonitorXMwaitXLockable(MonitorXMwaitXLockable&& rhs) = default; ~MonitorXMwaitXLockable() { } @@ -334,78 +406,5 @@ namespace ATG } }; #pragma warning (pop) -#endif // !__clang__ || __MWAITX__ - - ////////////////////////////////////////////////////////////////////////// - /// - /// Event object that attempts to stay at user level as much as possible - /// The object will only go to kernel mode if there is actually a thread waiting on the event - /// This allows for the maximum performance. - /// Interfaces follow the C++11 TimeLockable concept - /// The template parameter on manual reset is used to allow the compiler to optimize out the conditional - /// - ////////////////////////////////////////////////////////////////////////// - template - class UserBarrier - { - private: - std::atomic m_barrierValue; - uint64_t m_initialValue; - UserEventLockable m_blockEvent; - uint32_t m_threadOwnerID; - - public: - /// The UserBarrier cannot be copied - UserBarrier(const UserBarrier&) = delete; - UserBarrier& operator=(const UserBarrier&) = delete; - - UserBarrier(uint64_t initialValue = 1) : m_barrierValue(initialValue), m_initialValue(initialValue), m_blockEvent(false), m_threadOwnerID(0) { } - UserBarrier(UserBarrier&& rhs) = default; - ~UserBarrier() { } - - void clearOwner() { m_threadOwnerID = 0; } - - bool enterBarrier(bool block = false) - { - assert(m_barrierValue != 0); - if (threadOwner) - { - if (m_threadOwnerID == 0) - m_threadOwnerID = GetCurrentThreadId(); - } - uint64_t myValue = m_barrierValue.fetch_sub(1); - if (myValue == 1) - { - m_blockEvent.SetEvent(); - return true; - } - else if (block) - { - m_blockEvent.lock(); - } - else - { - while (m_barrierValue.load() != 0); - } - return false; - } - - bool reset() { return reset(m_initialValue); } - bool reset(uint64_t newValue) - { - if (threadOwner) - { - if (m_threadOwnerID != GetCurrentThreadId()) - { - if (InterlockedCompareExchange(&m_threadOwnerID, GetCurrentThreadId(), 0) != 0) - return false; - } - } - m_initialValue = newValue; - m_barrierValue = newValue; - m_blockEvent.SetEvent(); - m_blockEvent.ResetEvent(); - return true; - } - }; +#endif } diff --git a/Kits/ATGTK/d3dx12.h b/Kits/ATGTK/d3dx12.h index 42f26a6..e873d96 100644 --- a/Kits/ATGTK/d3dx12.h +++ b/Kits/ATGTK/d3dx12.h @@ -76,7 +76,12 @@ struct CD3DX12_VIEWPORT : public D3D12_VIEWPORT FLOAT minDepth = D3D12_MIN_DEPTH, FLOAT maxDepth = D3D12_MAX_DEPTH ) noexcept { +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pResource->GetDesc(&tmpDesc); +#endif const UINT64 SubresourceWidth = Desc.Width >> mipSlice; const UINT64 SubresourceHeight = Desc.Height >> mipSlice; switch (Desc.Dimension) @@ -2040,7 +2045,12 @@ inline UINT64 GetRequiredIntermediateSize( _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources) noexcept { +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif UINT64 RequiredSize = 0; ID3D12Device* pDevice = nullptr; @@ -2066,8 +2076,14 @@ inline UINT64 UpdateSubresources( _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept { // Minor validation +#if defined(_MSC_VER) || !defined(_WIN32) const auto IntermediateDesc = pIntermediate->GetDesc(); const auto DestinationDesc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc1, tmpDesc2; + const auto& IntermediateDesc = *pIntermediate->GetDesc(&tmpDesc1); + const auto& DestinationDesc = *pDestinationResource->GetDesc(&tmpDesc2); +#endif if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || RequiredSize > SIZE_T(-1) || @@ -2125,8 +2141,14 @@ inline UINT64 UpdateSubresources( _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_INFO* pSrcData) noexcept { // Minor validation +#if defined(_MSC_VER) || !defined(_WIN32) const auto IntermediateDesc = pIntermediate->GetDesc(); const auto DestinationDesc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc1, tmpDesc2; + const auto& IntermediateDesc = *pIntermediate->GetDesc(&tmpDesc1); + const auto& DestinationDesc = *pDestinationResource->GetDesc(&tmpDesc2); +#endif if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || RequiredSize > SIZE_T(-1) || @@ -2194,7 +2216,12 @@ inline UINT64 UpdateSubresources( auto pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); auto pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif ID3D12Device* pDevice = nullptr; pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast(&pDevice)); pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); @@ -2232,7 +2259,12 @@ inline UINT64 UpdateSubresources( auto pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); auto pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif ID3D12Device* pDevice = nullptr; pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast(&pDevice)); pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); @@ -2260,7 +2292,12 @@ inline UINT64 UpdateSubresources( UINT NumRows[MaxSubresources]; UINT64 RowSizesInBytes[MaxSubresources]; +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif ID3D12Device* pDevice = nullptr; pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast(&pDevice)); pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize); @@ -2287,7 +2324,12 @@ inline UINT64 UpdateSubresources( UINT NumRows[MaxSubresources]; UINT64 RowSizesInBytes[MaxSubresources]; +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif ID3D12Device* pDevice = nullptr; pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast(&pDevice)); pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize); @@ -4071,20 +4113,20 @@ public: D3D12_BARRIER_SUBRESOURCE_RANGE{ Subresource, 0, 0, 0, 0, 0 } {} CD3DX12_BARRIER_SUBRESOURCE_RANGE( - UINT FirstMipLevel, - UINT NumMips, - UINT FirstArraySlice, - UINT NumArraySlices, - UINT FirstPlane = 0, - UINT NumPlanes = 1) noexcept : + UINT firstMipLevel, + UINT numMips, + UINT firstArraySlice, + UINT numArraySlices, + UINT firstPlane = 0, + UINT numPlanes = 1) noexcept : D3D12_BARRIER_SUBRESOURCE_RANGE { - FirstMipLevel, - NumMips, - FirstArraySlice, - NumArraySlices, - FirstPlane, - NumPlanes + firstMipLevel, + numMips, + firstArraySlice, + numArraySlices, + firstPlane, + numPlanes } {} }; diff --git a/Kits/ATGTelemetry/GDK/ATGTelemetry.cpp b/Kits/ATGTelemetry/GDK/ATGTelemetry.cpp index 0cbb993..8f4b3db 100644 --- a/Kits/ATGTelemetry/GDK/ATGTelemetry.cpp +++ b/Kits/ATGTelemetry/GDK/ATGTelemetry.cpp @@ -45,6 +45,7 @@ using namespace ATG; class ATGTelemetry { public: + bool m_bHCInitialized{ false }; ~ATGTelemetry() { #if _GAMING_XBOX @@ -56,6 +57,14 @@ public: #endif } + void Cleanup() + { + if (m_bHCInitialized) + { + HCCleanup(); + } + } + void SendTelemetry() { #if _GAMING_XBOX @@ -86,6 +95,7 @@ private: { return; } + m_bHCInitialized = true; auto *async = new XAsyncBlock{}; async->queue = nullptr; @@ -464,4 +474,13 @@ void ATG::SendLaunchTelemetry() s_atgTelem->SendTelemetry(); } + +void ATG::CleanupTelemetry() +{ + if (s_atgTelem) + { + s_atgTelem->Cleanup(); + } + s_atgTelem = nullptr; +} #endif diff --git a/Kits/ATGTelemetry/GDK/ATGTelemetry.h b/Kits/ATGTelemetry/GDK/ATGTelemetry.h index 6a0ff15..bf03c62 100644 --- a/Kits/ATGTelemetry/GDK/ATGTelemetry.h +++ b/Kits/ATGTelemetry/GDK/ATGTelemetry.h @@ -20,8 +20,10 @@ namespace ATG #ifdef ATG_ENABLE_TELEMETRY // Sends sample launch telemetry void SendLaunchTelemetry(); + void CleanupTelemetry(); #else void SendLaunchTelemetry() {}; + void CleanupTelemetry() {}; #endif -} \ No newline at end of file +} diff --git a/Kits/DirectXTK12/Audio/SoundCommon.cpp b/Kits/DirectXTK12/Audio/SoundCommon.cpp index d01af20..418c704 100644 --- a/Kits/DirectXTK12/Audio/SoundCommon.cpp +++ b/Kits/DirectXTK12/Audio/SoundCommon.cpp @@ -822,9 +822,63 @@ void SoundEffectInstanceBase::Apply3D(const X3DAUDIO_LISTENER& listener, const X //====================================================================================== -// AudioEmitter helper +// AudioListener/Emitter helpers //====================================================================================== +namespace +{ + inline bool IsValid(const X3DAUDIO_CONE& cone) noexcept + { + // These match the validation ranges in X3DAudio. + if (cone.InnerAngle < 0.f || cone.InnerAngle > X3DAUDIO_2PI) + return false; + + if (cone.OuterAngle < 0.f || cone.OuterAngle > X3DAUDIO_2PI) + return false; + + if (cone.InnerAngle > cone.OuterAngle) + return false; + + if (cone.InnerVolume < 0.f || cone.InnerVolume > 2.f) + return false; + + if (cone.OuterVolume < 0.f || cone.OuterVolume > 2.f) + return false; + + if (cone.InnerLPF < 0.f || cone.InnerLPF > 1.f) + return false; + + if (cone.OuterLPF < 0.f || cone.OuterLPF > 1.f) + return false; + + if (cone.InnerReverb < 0.f || cone.InnerReverb > 2.f) + return false; + + if (cone.OuterReverb < 0.f || cone.OuterReverb > 2.f) + return false; + + return true; + } +} + +void AudioListener::SetCone(const X3DAUDIO_CONE& listenerCone) +{ + if (!::IsValid(listenerCone)) + throw std::invalid_argument("X3DAUDIO_CONE values out of range"); + + ListenerCone = listenerCone; + pCone = &ListenerCone; +} + +void AudioEmitter::SetCone(const X3DAUDIO_CONE& emitterCone) +{ + if (!::IsValid(emitterCone)) + throw std::invalid_argument("X3DAUDIO_CONE values out of range"); + + EmitterCone = emitterCone; + pCone = &EmitterCone; +} + namespace { // **Note these constants came from xact3d3.h in the legacy DirectX SDK** @@ -891,3 +945,17 @@ void AudioEmitter::EnableDefaultMultiChannel(unsigned int channels, float radius memset(EmitterAzimuths, 0, sizeof(float) * size_t(channels)); } } + +namespace +{ + // **Note these match the defaults from xact3d3.h in the legacy DirectX SDK** + constexpr X3DAUDIO_DISTANCE_CURVE_POINT c_defaultCurvePoints[2] = { { 0.0f, 1.0f }, { 1.0f, 1.0f } }; + constexpr X3DAUDIO_DISTANCE_CURVE c_defaultCurve = { const_cast(c_defaultCurvePoints), 2 }; +} + +void AudioEmitter::EnableDefaultCurves() noexcept +{ + pVolumeCurve = const_cast(&c_defaultCurve); + pLFECurve = const_cast(&c_defaultCurve); + pLPFDirectCurve = pLPFReverbCurve = pReverbCurve = nullptr; +} diff --git a/Kits/DirectXTK12/DirectXTK12_GDK_2019.vcxproj b/Kits/DirectXTK12/DirectXTK12_GDK_2019.vcxproj index 73020cf..a27cbd7 100644 --- a/Kits/DirectXTK12/DirectXTK12_GDK_2019.vcxproj +++ b/Kits/DirectXTK12/DirectXTK12_GDK_2019.vcxproj @@ -435,6 +435,7 @@ true /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) Level4 + true 6.0 @@ -464,6 +465,7 @@ true /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) Level4 + true 6.0 diff --git a/Kits/DirectXTK12/DirectXTK12_GRDK_2019.vcxproj b/Kits/DirectXTK12/DirectXTK12_GRDK_2019.vcxproj index 37c3850..3e7a15b 100644 --- a/Kits/DirectXTK12/DirectXTK12_GRDK_2019.vcxproj +++ b/Kits/DirectXTK12/DirectXTK12_GRDK_2019.vcxproj @@ -113,6 +113,7 @@ true /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) Level4 + true 6.0 @@ -142,6 +143,7 @@ true /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) Level4 + true 6.0 diff --git a/Kits/DirectXTK12/Inc/Audio.h b/Kits/DirectXTK12/Inc/Audio.h index 6b8a9b3..d63c7c3 100644 --- a/Kits/DirectXTK12/Inc/Audio.h +++ b/Kits/DirectXTK12/Inc/Audio.h @@ -434,10 +434,12 @@ namespace DirectX //---------------------------------------------------------------------------------- struct AudioListener : public X3DAUDIO_LISTENER { - AudioListener() noexcept - { - memset(this, 0, sizeof(X3DAUDIO_LISTENER)); + X3DAUDIO_CONE ListenerCone; + AudioListener() noexcept : + X3DAUDIO_LISTENER{}, + ListenerCone{} + { OrientFront.z = -1.f; OrientTop.y = 1.f; @@ -486,8 +488,8 @@ namespace DirectX XMStoreFloat3(reinterpret_cast(&OrientTop), up); } + // Updates velocity and orientation by tracking changes in position over time. void XM_CALLCONV Update(FXMVECTOR newPos, XMVECTOR upDir, float dt) noexcept - // Updates velocity and orientation by tracking changes in position over time... { if (dt > 0.f) { @@ -511,19 +513,27 @@ namespace DirectX XMStoreFloat3(reinterpret_cast(&Position), newPos); } } + + void __cdecl SetOmnidirectional() noexcept + { + pCone = nullptr; + } + + void __cdecl SetCone(const X3DAUDIO_CONE& listenerCone); }; //---------------------------------------------------------------------------------- struct AudioEmitter : public X3DAUDIO_EMITTER { - float EmitterAzimuths[XAUDIO2_MAX_AUDIO_CHANNELS]; + X3DAUDIO_CONE EmitterCone; + float EmitterAzimuths[XAUDIO2_MAX_AUDIO_CHANNELS]; AudioEmitter() noexcept : + X3DAUDIO_EMITTER{}, + EmitterCone{}, EmitterAzimuths{} { - memset(this, 0, sizeof(X3DAUDIO_EMITTER)); - OrientFront.z = -1.f; OrientTop.y = @@ -580,8 +590,8 @@ namespace DirectX XMStoreFloat3(reinterpret_cast(&OrientTop), up); } + // Updates velocity and orientation by tracking changes in position over time. void XM_CALLCONV Update(FXMVECTOR newPos, XMVECTOR upDir, float dt) noexcept - // Updates velocity and orientation by tracking changes in position over time... { if (dt > 0.f) { @@ -606,7 +616,19 @@ namespace DirectX } } + void __cdecl SetOmnidirectional() noexcept + { + pCone = nullptr; + } + + // Only used for single-channel emitters. + void __cdecl SetCone(const X3DAUDIO_CONE& emitterCone); + + // Set multi-channel emitter azimuths based on speaker configuration geometry. void __cdecl EnableDefaultMultiChannel(unsigned int channels, float radius = 1.f); + + // Set default volume, LFE, LPF, and reverb curves. + void __cdecl EnableDefaultCurves() noexcept; }; diff --git a/Kits/DirectXTK12/Inc/CommonStates.h b/Kits/DirectXTK12/Inc/CommonStates.h index 8e7e330..7aba709 100644 --- a/Kits/DirectXTK12/Inc/CommonStates.h +++ b/Kits/DirectXTK12/Inc/CommonStates.h @@ -25,71 +25,74 @@ namespace DirectX { - class CommonStates + inline namespace DX12 { - public: - explicit CommonStates(_In_ ID3D12Device* device); - - CommonStates(CommonStates&&) noexcept; - CommonStates& operator = (CommonStates&&) noexcept; - - CommonStates(const CommonStates&) = delete; - CommonStates& operator = (const CommonStates&) = delete; - - virtual ~CommonStates(); - - // Blend states. - static const D3D12_BLEND_DESC Opaque; - static const D3D12_BLEND_DESC AlphaBlend; - static const D3D12_BLEND_DESC Additive; - static const D3D12_BLEND_DESC NonPremultiplied; - - // Depth stencil states. - static const D3D12_DEPTH_STENCIL_DESC DepthNone; - static const D3D12_DEPTH_STENCIL_DESC DepthDefault; - static const D3D12_DEPTH_STENCIL_DESC DepthRead; - static const D3D12_DEPTH_STENCIL_DESC DepthReverseZ; - static const D3D12_DEPTH_STENCIL_DESC DepthReadReverseZ; - - // Rasterizer states. - static const D3D12_RASTERIZER_DESC CullNone; - static const D3D12_RASTERIZER_DESC CullClockwise; - static const D3D12_RASTERIZER_DESC CullCounterClockwise; - static const D3D12_RASTERIZER_DESC Wireframe; - - // Static sampler states. - static const D3D12_STATIC_SAMPLER_DESC StaticPointWrap(unsigned int shaderRegister, D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, unsigned int registerSpace = 0) noexcept; - static const D3D12_STATIC_SAMPLER_DESC StaticPointClamp(unsigned int shaderRegister, D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, unsigned int registerSpace = 0) noexcept; - static const D3D12_STATIC_SAMPLER_DESC StaticLinearWrap(unsigned int shaderRegister, D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, unsigned int registerSpace = 0) noexcept; - static const D3D12_STATIC_SAMPLER_DESC StaticLinearClamp(unsigned int shaderRegister, D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, unsigned int registerSpace = 0) noexcept; - static const D3D12_STATIC_SAMPLER_DESC StaticAnisotropicWrap(unsigned int shaderRegister, D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, unsigned int registerSpace = 0) noexcept; - static const D3D12_STATIC_SAMPLER_DESC StaticAnisotropicClamp(unsigned int shaderRegister, D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, unsigned int registerSpace = 0) noexcept; - - // Sampler states. - D3D12_GPU_DESCRIPTOR_HANDLE PointWrap() const; - D3D12_GPU_DESCRIPTOR_HANDLE PointClamp() const; - D3D12_GPU_DESCRIPTOR_HANDLE LinearWrap() const; - D3D12_GPU_DESCRIPTOR_HANDLE LinearClamp() const; - D3D12_GPU_DESCRIPTOR_HANDLE AnisotropicWrap() const; - D3D12_GPU_DESCRIPTOR_HANDLE AnisotropicClamp() const; - - // These index into the heap returned by SamplerDescriptorHeap - enum class SamplerIndex + class CommonStates { - PointWrap, - PointClamp, - LinearWrap, - LinearClamp, - AnisotropicWrap, - AnisotropicClamp, - Count + public: + explicit CommonStates(_In_ ID3D12Device* device); + + CommonStates(CommonStates&&) noexcept; + CommonStates& operator = (CommonStates&&) noexcept; + + CommonStates(const CommonStates&) = delete; + CommonStates& operator = (const CommonStates&) = delete; + + virtual ~CommonStates(); + + // Blend states. + static const D3D12_BLEND_DESC Opaque; + static const D3D12_BLEND_DESC AlphaBlend; + static const D3D12_BLEND_DESC Additive; + static const D3D12_BLEND_DESC NonPremultiplied; + + // Depth stencil states. + static const D3D12_DEPTH_STENCIL_DESC DepthNone; + static const D3D12_DEPTH_STENCIL_DESC DepthDefault; + static const D3D12_DEPTH_STENCIL_DESC DepthRead; + static const D3D12_DEPTH_STENCIL_DESC DepthReverseZ; + static const D3D12_DEPTH_STENCIL_DESC DepthReadReverseZ; + + // Rasterizer states. + static const D3D12_RASTERIZER_DESC CullNone; + static const D3D12_RASTERIZER_DESC CullClockwise; + static const D3D12_RASTERIZER_DESC CullCounterClockwise; + static const D3D12_RASTERIZER_DESC Wireframe; + + // Static sampler states. + static const D3D12_STATIC_SAMPLER_DESC StaticPointWrap(unsigned int shaderRegister, D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, unsigned int registerSpace = 0) noexcept; + static const D3D12_STATIC_SAMPLER_DESC StaticPointClamp(unsigned int shaderRegister, D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, unsigned int registerSpace = 0) noexcept; + static const D3D12_STATIC_SAMPLER_DESC StaticLinearWrap(unsigned int shaderRegister, D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, unsigned int registerSpace = 0) noexcept; + static const D3D12_STATIC_SAMPLER_DESC StaticLinearClamp(unsigned int shaderRegister, D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, unsigned int registerSpace = 0) noexcept; + static const D3D12_STATIC_SAMPLER_DESC StaticAnisotropicWrap(unsigned int shaderRegister, D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, unsigned int registerSpace = 0) noexcept; + static const D3D12_STATIC_SAMPLER_DESC StaticAnisotropicClamp(unsigned int shaderRegister, D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, unsigned int registerSpace = 0) noexcept; + + // Sampler states. + D3D12_GPU_DESCRIPTOR_HANDLE PointWrap() const; + D3D12_GPU_DESCRIPTOR_HANDLE PointClamp() const; + D3D12_GPU_DESCRIPTOR_HANDLE LinearWrap() const; + D3D12_GPU_DESCRIPTOR_HANDLE LinearClamp() const; + D3D12_GPU_DESCRIPTOR_HANDLE AnisotropicWrap() const; + D3D12_GPU_DESCRIPTOR_HANDLE AnisotropicClamp() const; + + // These index into the heap returned by SamplerDescriptorHeap + enum class SamplerIndex + { + PointWrap, + PointClamp, + LinearWrap, + LinearClamp, + AnisotropicWrap, + AnisotropicClamp, + Count + }; + + ID3D12DescriptorHeap* Heap() const noexcept; + + private: + class Impl; + + std::unique_ptr pImpl; }; - - ID3D12DescriptorHeap* Heap() const noexcept; - - private: - class Impl; - - std::unique_ptr pImpl; - }; + } } diff --git a/Kits/DirectXTK12/Inc/DDSTextureLoader.h b/Kits/DirectXTK12/Inc/DDSTextureLoader.h index c24d49f..414c767 100644 --- a/Kits/DirectXTK12/Inc/DDSTextureLoader.h +++ b/Kits/DirectXTK12/Inc/DDSTextureLoader.h @@ -48,13 +48,17 @@ namespace DirectX }; #endif - enum DDS_LOADER_FLAGS : uint32_t + inline namespace DX12 { - DDS_LOADER_DEFAULT = 0, - DDS_LOADER_FORCE_SRGB = 0x1, - DDS_LOADER_MIP_AUTOGEN = 0x8, - DDS_LOADER_MIP_RESERVE = 0x10, - }; + enum DDS_LOADER_FLAGS : uint32_t + { + DDS_LOADER_DEFAULT = 0, + DDS_LOADER_FORCE_SRGB = 0x1, + DDS_LOADER_IGNORE_SRGB = 0x2, + DDS_LOADER_MIP_AUTOGEN = 0x8, + DDS_LOADER_MIP_RESERVE = 0x10, + }; + } // Standard version HRESULT __cdecl LoadDDSTextureFromMemory( @@ -153,7 +157,10 @@ namespace DirectX #pragma clang diagnostic ignored "-Wdeprecated-dynamic-exception-spec" #endif - DEFINE_ENUM_FLAG_OPERATORS(DDS_LOADER_FLAGS); + inline namespace DX12 + { + DEFINE_ENUM_FLAG_OPERATORS(DDS_LOADER_FLAGS); + } #ifdef __clang__ #pragma clang diagnostic pop diff --git a/Kits/DirectXTK12/Inc/DirectXHelpers.h b/Kits/DirectXTK12/Inc/DirectXHelpers.h index b1e6060..7b44118 100644 --- a/Kits/DirectXTK12/Inc/DirectXHelpers.h +++ b/Kits/DirectXTK12/Inc/DirectXHelpers.h @@ -139,7 +139,12 @@ namespace DirectX // Helper for obtaining texture size inline XMUINT2 GetTextureSize(_In_ ID3D12Resource* tex) noexcept { +#if defined(_MSC_VER) || !defined(_WIN32) const auto desc = tex->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& desc = *tex->GetDesc(&tmpDesc); +#endif return XMUINT2(static_cast(desc.Width), static_cast(desc.Height)); } @@ -281,32 +286,35 @@ namespace DirectX std::vector mBarriers; }; - // Helper to check for power-of-2 - template - constexpr bool IsPowerOf2(T x) noexcept { return ((x != 0) && !(x & (x - 1))); } - - // Helpers for aligning values by a power of 2 - template - inline T AlignDown(T size, size_t alignment) noexcept + inline namespace DX12 { - if (alignment > 0) - { - assert(((alignment - 1) & alignment) == 0); - auto mask = static_cast(alignment - 1); - return size & ~mask; - } - return size; - } + // Helper to check for power-of-2 + template + constexpr bool IsPowerOf2(T x) noexcept { return ((x != 0) && !(x & (x - 1))); } - template - inline T AlignUp(T size, size_t alignment) noexcept - { - if (alignment > 0) + // Helpers for aligning values by a power of 2 + template + inline T AlignDown(T size, size_t alignment) noexcept { - assert(((alignment - 1) & alignment) == 0); - auto mask = static_cast(alignment - 1); - return (size + mask) & ~mask; + if (alignment > 0) + { + assert(((alignment - 1) & alignment) == 0); + auto mask = static_cast(alignment - 1); + return size & ~mask; + } + return size; + } + + template + inline T AlignUp(T size, size_t alignment) noexcept + { + if (alignment > 0) + { + assert(((alignment - 1) & alignment) == 0); + auto mask = static_cast(alignment - 1); + return (size + mask) & ~mask; + } + return size; } - return size; } } diff --git a/Kits/DirectXTK12/Inc/EffectPipelineStateDescription.h b/Kits/DirectXTK12/Inc/EffectPipelineStateDescription.h index 96c6327..60451d8 100644 --- a/Kits/DirectXTK12/Inc/EffectPipelineStateDescription.h +++ b/Kits/DirectXTK12/Inc/EffectPipelineStateDescription.h @@ -67,6 +67,7 @@ namespace DirectX const D3D12_SHADER_BYTECODE& pixelShader, _Outptr_ ID3D12PipelineState** pPipelineState) const; + #if defined(_MSC_VER) || !defined(_WIN32) D3D12_GRAPHICS_PIPELINE_STATE_DESC GetDesc() const noexcept { D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; @@ -84,6 +85,28 @@ namespace DirectX psoDesc.NodeMask = renderTargetState.nodeMask; return psoDesc; } + #else + D3D12_GRAPHICS_PIPELINE_STATE_DESC* GetDesc(_Out_ D3D12_GRAPHICS_PIPELINE_STATE_DESC* psoDesc) const noexcept + { + if (!psoDesc) + return nullptr; + + *psoDesc = {}; + psoDesc->BlendState = blendDesc; + psoDesc->SampleMask = renderTargetState.sampleMask; + psoDesc->RasterizerState = rasterizerDesc; + psoDesc->DepthStencilState = depthStencilDesc; + psoDesc->InputLayout = inputLayout; + psoDesc->IBStripCutValue = stripCutValue; + psoDesc->PrimitiveTopologyType = primitiveTopology; + psoDesc->NumRenderTargets = renderTargetState.numRenderTargets; + memcpy(psoDesc->RTVFormats, renderTargetState.rtvFormats, sizeof(DXGI_FORMAT) * D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT); + psoDesc->DSVFormat = renderTargetState.dsvFormat; + psoDesc->SampleDesc = renderTargetState.sampleDesc; + psoDesc->NodeMask = renderTargetState.nodeMask; + return psoDesc; + } + #endif uint32_t ComputeHash() const noexcept; diff --git a/Kits/DirectXTK12/Inc/Effects.h b/Kits/DirectXTK12/Inc/Effects.h index 3ecaabc..235181f 100644 --- a/Kits/DirectXTK12/Inc/Effects.h +++ b/Kits/DirectXTK12/Inc/Effects.h @@ -36,892 +36,895 @@ namespace DirectX class DescriptorHeap; class ResourceUploadBatch; - //---------------------------------------------------------------------------------- - // Abstract interface representing any effect which can be applied onto a D3D device context. - class IEffect + inline namespace DX12 { - public: - virtual ~IEffect() = default; - - IEffect(const IEffect&) = delete; - IEffect& operator=(const IEffect&) = delete; - - virtual void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) = 0; - - protected: - IEffect() = default; - IEffect(IEffect&&) = default; - IEffect& operator=(IEffect&&) = default; - }; - - - // Abstract interface for effects with world, view, and projection matrices. - class IEffectMatrices - { - public: - virtual ~IEffectMatrices() = default; - - IEffectMatrices(const IEffectMatrices&) = delete; - IEffectMatrices& operator=(const IEffectMatrices&) = delete; - - virtual void XM_CALLCONV SetWorld(FXMMATRIX value) = 0; - virtual void XM_CALLCONV SetView(FXMMATRIX value) = 0; - virtual void XM_CALLCONV SetProjection(FXMMATRIX value) = 0; - virtual void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection); - - protected: - IEffectMatrices() = default; - IEffectMatrices(IEffectMatrices&&) = default; - IEffectMatrices& operator=(IEffectMatrices&&) = default; - }; - - - // Abstract interface for effects which support directional lighting. - class IEffectLights - { - public: - virtual ~IEffectLights() = default; - - IEffectLights(const IEffectLights&) = delete; - IEffectLights& operator=(const IEffectLights&) = delete; - - virtual void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) = 0; - - virtual void __cdecl SetLightEnabled(int whichLight, bool value) = 0; - virtual void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) = 0; - virtual void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) = 0; - virtual void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) = 0; - - virtual void __cdecl EnableDefaultLighting() = 0; - - static constexpr int MaxDirectionalLights = 3; - - protected: - IEffectLights() = default; - IEffectLights(IEffectLights&&) = default; - IEffectLights& operator=(IEffectLights&&) = default; - }; - - - // Abstract interface for effects which support fog. - class IEffectFog - { - public: - virtual ~IEffectFog() = default; - - IEffectFog(const IEffectFog&) = delete; - IEffectFog& operator=(const IEffectFog&) = delete; - - virtual void __cdecl SetFogStart(float value) = 0; - virtual void __cdecl SetFogEnd(float value) = 0; - virtual void XM_CALLCONV SetFogColor(FXMVECTOR value) = 0; - - protected: - IEffectFog() = default; - IEffectFog(IEffectFog&&) = default; - IEffectFog& operator=(IEffectFog&&) = default; - }; - - - // Abstract interface for effects which support skinning - class IEffectSkinning - { - public: - virtual ~IEffectSkinning() = default; - - IEffectSkinning(const IEffectSkinning&) = delete; - IEffectSkinning& operator=(const IEffectSkinning&) = delete; - - virtual void __cdecl SetBoneTransforms(_In_reads_(count) XMMATRIX const* value, size_t count) = 0; - virtual void __cdecl ResetBoneTransforms() = 0; - - static constexpr int MaxBones = 72; - - protected: - IEffectSkinning() = default; - IEffectSkinning(IEffectSkinning&&) = default; - IEffectSkinning& operator=(IEffectSkinning&&) = default; - }; - - - //---------------------------------------------------------------------------------- - namespace EffectFlags - { - constexpr uint32_t None = 0x00; - constexpr uint32_t Fog = 0x01; - constexpr uint32_t Lighting = 0x02; - - constexpr uint32_t PerPixelLighting = 0x04 | Lighting; - // per pixel lighting implies lighting enabled - - constexpr uint32_t VertexColor = 0x08; - constexpr uint32_t Texture = 0x10; - constexpr uint32_t Instancing = 0x20; - - constexpr uint32_t Specular = 0x100; - // enable optional specular/specularMap feature - - constexpr uint32_t Emissive = 0x200; - // enable optional emissive/emissiveMap feature - - constexpr uint32_t Fresnel = 0x400; - // enable optional Fresnel feature - - constexpr uint32_t Velocity = 0x800; - // enable optional velocity feature - - constexpr uint32_t BiasedVertexNormals = 0x10000; - // compressed vertex normals need x2 bias - } - - - //---------------------------------------------------------------------------------- - // Built-in shader supports optional texture mapping, vertex coloring, directional lighting, and fog. - class BasicEffect : public IEffect, public IEffectMatrices, public IEffectLights, public IEffectFog - { - public: - BasicEffect(_In_ ID3D12Device* device, uint32_t effectFlags, const EffectPipelineStateDescription& pipelineDescription); - - BasicEffect(BasicEffect&&) noexcept; - BasicEffect& operator= (BasicEffect&&) noexcept; - - BasicEffect(BasicEffect const&) = delete; - BasicEffect& operator= (BasicEffect const&) = delete; - - ~BasicEffect() override; - - // IEffect methods. - void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; - - // Camera settings. - void XM_CALLCONV SetWorld(FXMMATRIX value) override; - void XM_CALLCONV SetView(FXMMATRIX value) override; - void XM_CALLCONV SetProjection(FXMMATRIX value) override; - void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; - - // Material settings. - void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); - void XM_CALLCONV SetEmissiveColor(FXMVECTOR value); - void XM_CALLCONV SetSpecularColor(FXMVECTOR value); - void __cdecl SetSpecularPower(float value); - void __cdecl DisableSpecular(); - void __cdecl SetAlpha(float value); - void XM_CALLCONV SetColorAndAlpha(FXMVECTOR value); - - // Light settings. - void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) override; - - void __cdecl SetLightEnabled(int whichLight, bool value) override; - void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) override; - void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) override; - void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) override; - - void __cdecl EnableDefaultLighting() override; - - // Fog settings. - void __cdecl SetFogStart(float value) override; - void __cdecl SetFogEnd(float value) override; - void XM_CALLCONV SetFogColor(FXMVECTOR value) override; - - // Texture setting. - void __cdecl SetTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); - - private: - // Private implementation. - class Impl; - - std::unique_ptr pImpl; - }; - - - // Built-in shader supports per-pixel alpha testing. - class AlphaTestEffect : public IEffect, public IEffectMatrices, public IEffectFog - { - public: - AlphaTestEffect(_In_ ID3D12Device* device, uint32_t effectFlags, - const EffectPipelineStateDescription& pipelineDescription, - D3D12_COMPARISON_FUNC alphaFunction = D3D12_COMPARISON_FUNC_GREATER); - - AlphaTestEffect(AlphaTestEffect&&) noexcept; - AlphaTestEffect& operator= (AlphaTestEffect&&) noexcept; - - AlphaTestEffect(AlphaTestEffect const&) = delete; - AlphaTestEffect& operator= (AlphaTestEffect const&) = delete; - - ~AlphaTestEffect() override; - - // IEffect methods. - void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; - - // Camera settings. - void XM_CALLCONV SetWorld(FXMMATRIX value) override; - void XM_CALLCONV SetView(FXMMATRIX value) override; - void XM_CALLCONV SetProjection(FXMMATRIX value) override; - void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; - - // Material settings. - void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); - void __cdecl SetAlpha(float value); - void XM_CALLCONV SetColorAndAlpha(FXMVECTOR value); - - // Fog settings. - void __cdecl SetFogStart(float value) override; - void __cdecl SetFogEnd(float value) override; - void XM_CALLCONV SetFogColor(FXMVECTOR value) override; - - // Texture setting. - void __cdecl SetTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); - - // Alpha test settings. - void __cdecl SetReferenceAlpha(int value); - - private: - // Private implementation. - class Impl; - - std::unique_ptr pImpl; - }; - - - // Built-in shader supports two layer multitexturing (eg. for lightmaps or detail textures). - class DualTextureEffect : public IEffect, public IEffectMatrices, public IEffectFog - { - public: - DualTextureEffect(_In_ ID3D12Device* device, uint32_t effectFlags, - const EffectPipelineStateDescription& pipelineDescription); - - DualTextureEffect(DualTextureEffect&&) noexcept; - DualTextureEffect& operator= (DualTextureEffect&&) noexcept; - - DualTextureEffect(DualTextureEffect const&) = delete; - DualTextureEffect& operator= (DualTextureEffect const&) = delete; - - ~DualTextureEffect() override; - - // IEffect methods. - void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; - - // Camera settings. - void XM_CALLCONV SetWorld(FXMMATRIX value) override; - void XM_CALLCONV SetView(FXMMATRIX value) override; - void XM_CALLCONV SetProjection(FXMMATRIX value) override; - void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; - - // Material settings. - void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); - void __cdecl SetAlpha(float value); - void XM_CALLCONV SetColorAndAlpha(FXMVECTOR value); - - // Fog settings. - void __cdecl SetFogStart(float value) override; - void __cdecl SetFogEnd(float value) override; - void XM_CALLCONV SetFogColor(FXMVECTOR value) override; - - // Texture settings. - void __cdecl SetTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); - void __cdecl SetTexture2(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); - - private: - // Private implementation. - class Impl; - - std::unique_ptr pImpl; - }; - - - // Built-in shader supports cubic environment mapping. - class EnvironmentMapEffect : public IEffect, public IEffectMatrices, public IEffectLights, public IEffectFog - { - public: - enum Mapping + //------------------------------------------------------------------------------ + // Abstract interface representing any effect which can be applied onto a D3D device context. + class IEffect { - Mapping_Cube = 0, // Cubic environment map - Mapping_Sphere, // Spherical environment map - Mapping_DualParabola, // Dual-parabola environment map (requires Feature Level 10.0) + public: + virtual ~IEffect() = default; + + IEffect(const IEffect&) = delete; + IEffect& operator=(const IEffect&) = delete; + + virtual void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) = 0; + + protected: + IEffect() = default; + IEffect(IEffect&&) = default; + IEffect& operator=(IEffect&&) = default; }; - EnvironmentMapEffect(_In_ ID3D12Device* device, uint32_t effectFlags, - const EffectPipelineStateDescription& pipelineDescription, - Mapping mapping = Mapping_Cube); - EnvironmentMapEffect(EnvironmentMapEffect&&) noexcept; - EnvironmentMapEffect& operator= (EnvironmentMapEffect&&) noexcept; - - EnvironmentMapEffect(EnvironmentMapEffect const&) = delete; - EnvironmentMapEffect& operator= (EnvironmentMapEffect const&) = delete; - - ~EnvironmentMapEffect() override; - - // IEffect methods. - void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; - - // Camera settings. - void XM_CALLCONV SetWorld(FXMMATRIX value) override; - void XM_CALLCONV SetView(FXMMATRIX value) override; - void XM_CALLCONV SetProjection(FXMMATRIX value) override; - void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; - - // Material settings. - void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); - void XM_CALLCONV SetEmissiveColor(FXMVECTOR value); - void __cdecl SetAlpha(float value); - void XM_CALLCONV SetColorAndAlpha(FXMVECTOR value); - - // Light settings. - void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) override; - - void __cdecl SetLightEnabled(int whichLight, bool value) override; - void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) override; - void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) override; - - void __cdecl EnableDefaultLighting() override; - - // Fog settings. - void __cdecl SetFogStart(float value) override; - void __cdecl SetFogEnd(float value) override; - void XM_CALLCONV SetFogColor(FXMVECTOR value) override; - - // Texture setting. - void __cdecl SetTexture(D3D12_GPU_DESCRIPTOR_HANDLE texture, D3D12_GPU_DESCRIPTOR_HANDLE sampler); - - // Environment map settings. - void __cdecl SetEnvironmentMap(D3D12_GPU_DESCRIPTOR_HANDLE texture, D3D12_GPU_DESCRIPTOR_HANDLE sampler); - void __cdecl SetEnvironmentMapAmount(float value); - void XM_CALLCONV SetEnvironmentMapSpecular(FXMVECTOR value); - void __cdecl SetFresnelFactor(float value); - - private: - // Private implementation. - class Impl; - - std::unique_ptr pImpl; - - // Unsupported interface methods. - void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) override; - }; - - - // Built-in shader supports skinned animation. - class SkinnedEffect : public IEffect, public IEffectMatrices, public IEffectLights, public IEffectFog, public IEffectSkinning - { - public: - SkinnedEffect(_In_ ID3D12Device* device, uint32_t effectFlags, - const EffectPipelineStateDescription& pipelineDescription); - - SkinnedEffect(SkinnedEffect&&) noexcept; - SkinnedEffect& operator= (SkinnedEffect&&) noexcept; - - SkinnedEffect(SkinnedEffect const&) = delete; - SkinnedEffect& operator= (SkinnedEffect const&) = delete; - - ~SkinnedEffect() override; - - // IEffect methods. - void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; - - // Camera settings. - void XM_CALLCONV SetWorld(FXMMATRIX value) override; - void XM_CALLCONV SetView(FXMMATRIX value) override; - void XM_CALLCONV SetProjection(FXMMATRIX value) override; - void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; - - // Material settings. - void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); - void XM_CALLCONV SetEmissiveColor(FXMVECTOR value); - void XM_CALLCONV SetSpecularColor(FXMVECTOR value); - void __cdecl SetSpecularPower(float value); - void __cdecl DisableSpecular(); - void __cdecl SetAlpha(float value); - void XM_CALLCONV SetColorAndAlpha(FXMVECTOR value); - - // Light settings. - void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) override; - - void __cdecl SetLightEnabled(int whichLight, bool value) override; - void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) override; - void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) override; - void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) override; - - void __cdecl EnableDefaultLighting() override; - - // Fog settings. - void __cdecl SetFogStart(float value) override; - void __cdecl SetFogEnd(float value) override; - void XM_CALLCONV SetFogColor(FXMVECTOR value) override; - - // Texture setting. - void __cdecl SetTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); - - // Animation settings. - void __cdecl SetBoneTransforms(_In_reads_(count) XMMATRIX const* value, size_t count) override; - void __cdecl ResetBoneTransforms() override; - - private: - // Private implementation. - class Impl; - - std::unique_ptr pImpl; - }; - - - //---------------------------------------------------------------------------------- - // Built-in shader extends BasicEffect with normal map and optional specular map - class NormalMapEffect : public IEffect, public IEffectMatrices, public IEffectLights, public IEffectFog - { - public: - NormalMapEffect(_In_ ID3D12Device* device, uint32_t effectFlags, - const EffectPipelineStateDescription& pipelineDescription) : - NormalMapEffect(device, effectFlags, pipelineDescription, false) + // Abstract interface for effects with world, view, and projection matrices. + class IEffectMatrices { - } + public: + virtual ~IEffectMatrices() = default; - NormalMapEffect(NormalMapEffect&&) noexcept; - NormalMapEffect& operator= (NormalMapEffect&&) noexcept; + IEffectMatrices(const IEffectMatrices&) = delete; + IEffectMatrices& operator=(const IEffectMatrices&) = delete; - NormalMapEffect(NormalMapEffect const&) = delete; - NormalMapEffect& operator= (NormalMapEffect const&) = delete; + virtual void XM_CALLCONV SetWorld(FXMMATRIX value) = 0; + virtual void XM_CALLCONV SetView(FXMMATRIX value) = 0; + virtual void XM_CALLCONV SetProjection(FXMMATRIX value) = 0; + virtual void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection); - ~NormalMapEffect() override; - - // IEffect methods. - void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; - - // Camera settings. - void XM_CALLCONV SetWorld(FXMMATRIX value) override; - void XM_CALLCONV SetView(FXMMATRIX value) override; - void XM_CALLCONV SetProjection(FXMMATRIX value) override; - void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; - - // Material settings. - void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); - void XM_CALLCONV SetEmissiveColor(FXMVECTOR value); - void XM_CALLCONV SetSpecularColor(FXMVECTOR value); - void __cdecl SetSpecularPower(float value); - void __cdecl DisableSpecular(); - void __cdecl SetAlpha(float value); - void XM_CALLCONV SetColorAndAlpha(FXMVECTOR value); - - // Light settings. - void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) override; - - void __cdecl SetLightEnabled(int whichLight, bool value) override; - void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) override; - void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) override; - void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) override; - - void __cdecl EnableDefaultLighting() override; - - // Fog settings. - void __cdecl SetFogStart(float value) override; - void __cdecl SetFogEnd(float value) override; - void XM_CALLCONV SetFogColor(FXMVECTOR value) override; - - // Texture setting - albedo, normal and specular intensity - void __cdecl SetTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); - void __cdecl SetNormalTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); - void __cdecl SetSpecularTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); - - protected: - // Private implementation. - class Impl; - - std::unique_ptr pImpl; - - NormalMapEffect(_In_ ID3D12Device* device, uint32_t effectFlags, - const EffectPipelineStateDescription& pipelineDescription, bool skinningEnabled); - }; - - class SkinnedNormalMapEffect : public NormalMapEffect, public IEffectSkinning - { - public: - SkinnedNormalMapEffect(_In_ ID3D12Device* device, uint32_t effectFlags, - const EffectPipelineStateDescription& pipelineDescription) : - NormalMapEffect(device, effectFlags, pipelineDescription, true) - { - } - - SkinnedNormalMapEffect(SkinnedNormalMapEffect&&) = default; - SkinnedNormalMapEffect& operator= (SkinnedNormalMapEffect&&) = default; - - SkinnedNormalMapEffect(SkinnedNormalMapEffect const&) = delete; - SkinnedNormalMapEffect& operator= (SkinnedNormalMapEffect const&) = delete; - - // Animation settings. - void __cdecl SetBoneTransforms(_In_reads_(count) XMMATRIX const* value, size_t count) override; - void __cdecl ResetBoneTransforms() override; - }; - - - //---------------------------------------------------------------------------------- - // Built-in shader for Physically-Based Rendering (Roughness/Metalness) with Image-based lighting - class PBREffect : public IEffect, public IEffectMatrices, public IEffectLights - { - public: - PBREffect(_In_ ID3D12Device* device, uint32_t effectFlags, - const EffectPipelineStateDescription& pipelineDescription) : - PBREffect(device, effectFlags, pipelineDescription, false) - { - } - - PBREffect(PBREffect&&) noexcept; - PBREffect& operator= (PBREffect&&) noexcept; - - PBREffect(PBREffect const&) = delete; - PBREffect& operator= (PBREffect const&) = delete; - - ~PBREffect() override; - - // IEffect methods. - void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; - - // Camera settings. - void XM_CALLCONV SetWorld(FXMMATRIX value) override; - void XM_CALLCONV SetView(FXMMATRIX value) override; - void XM_CALLCONV SetProjection(FXMMATRIX value) override; - void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; - - // Light settings. - void __cdecl SetLightEnabled(int whichLight, bool value) override; - void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) override; - void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) override; - - void __cdecl EnableDefaultLighting() override; - - // PBR Settings. - void __cdecl SetAlpha(float value); - void XM_CALLCONV SetConstantAlbedo(FXMVECTOR value); - void __cdecl SetConstantMetallic(float value); - void __cdecl SetConstantRoughness(float value); - - // Texture settings. - void __cdecl SetAlbedoTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); - void __cdecl SetNormalTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); - void __cdecl SetRMATexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); - - void __cdecl SetEmissiveTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); - - void __cdecl SetSurfaceTextures( - D3D12_GPU_DESCRIPTOR_HANDLE albedo, - D3D12_GPU_DESCRIPTOR_HANDLE normal, - D3D12_GPU_DESCRIPTOR_HANDLE roughnessMetallicAmbientOcclusion, - D3D12_GPU_DESCRIPTOR_HANDLE sampler); - - void __cdecl SetIBLTextures( - D3D12_GPU_DESCRIPTOR_HANDLE radiance, - int numRadianceMips, - D3D12_GPU_DESCRIPTOR_HANDLE irradiance, - D3D12_GPU_DESCRIPTOR_HANDLE sampler); - - // Render target size, required for velocity buffer output. - void __cdecl SetRenderTargetSizeInPixels(int width, int height); - - protected: - // Private implementation. - class Impl; - - std::unique_ptr pImpl; - - PBREffect(_In_ ID3D12Device* device, uint32_t effectFlags, - const EffectPipelineStateDescription& pipelineDescription, bool skinningEnabled); - - // Unsupported interface methods. - void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) override; - void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) override; - }; - - class SkinnedPBREffect : public PBREffect, public IEffectSkinning - { - public: - SkinnedPBREffect(_In_ ID3D12Device* device, uint32_t effectFlags, - const EffectPipelineStateDescription& pipelineDescription) : - PBREffect(device, effectFlags, pipelineDescription, true) - { - } - - SkinnedPBREffect(SkinnedPBREffect&&) = default; - SkinnedPBREffect& operator= (SkinnedPBREffect&&) = default; - - SkinnedPBREffect(SkinnedPBREffect const&) = delete; - SkinnedPBREffect& operator= (SkinnedPBREffect const&) = delete; - - // Animation settings. - void __cdecl SetBoneTransforms(_In_reads_(count) XMMATRIX const* value, size_t count) override; - void __cdecl ResetBoneTransforms() override; - }; - - - //---------------------------------------------------------------------------------- - // Built-in shader for debug visualization of normals, tangents, etc. - class DebugEffect : public IEffect, public IEffectMatrices - { - public: - enum Mode - { - Mode_Default = 0, // Hemispherical ambient lighting - Mode_Normals, // RGB normals - Mode_Tangents, // RGB tangents - Mode_BiTangents, // RGB bi-tangents + protected: + IEffectMatrices() = default; + IEffectMatrices(IEffectMatrices&&) = default; + IEffectMatrices& operator=(IEffectMatrices&&) = default; }; - DebugEffect(_In_ ID3D12Device* device, uint32_t effectFlags, - const EffectPipelineStateDescription& pipelineDescription, - Mode debugMode = Mode_Default); - DebugEffect(DebugEffect&&) noexcept; - DebugEffect& operator= (DebugEffect&&) noexcept; - - DebugEffect(DebugEffect const&) = delete; - DebugEffect& operator= (DebugEffect const&) = delete; - - ~DebugEffect() override; - - // IEffect methods. - void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; - - // Camera settings. - void XM_CALLCONV SetWorld(FXMMATRIX value) override; - void XM_CALLCONV SetView(FXMMATRIX value) override; - void XM_CALLCONV SetProjection(FXMMATRIX value) override; - void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; - - // Debug Settings. - void XM_CALLCONV SetHemisphericalAmbientColor(FXMVECTOR upper, FXMVECTOR lower); - void __cdecl SetAlpha(float value); - - private: - // Private implementation. - class Impl; - - std::unique_ptr pImpl; - }; - - - //---------------------------------------------------------------------------------- - // Abstract interface to factory texture resources - class IEffectTextureFactory - { - public: - virtual ~IEffectTextureFactory() = default; - - IEffectTextureFactory(const IEffectTextureFactory&) = delete; - IEffectTextureFactory& operator=(const IEffectTextureFactory&) = delete; - - virtual size_t __cdecl CreateTexture(_In_z_ const wchar_t* name, int descriptorIndex) = 0; - - protected: - IEffectTextureFactory() = default; - IEffectTextureFactory(IEffectTextureFactory&&) = default; - IEffectTextureFactory& operator=(IEffectTextureFactory&&) = default; - }; - - - // Factory for sharing texture resources - class EffectTextureFactory : public IEffectTextureFactory - { - public: - EffectTextureFactory( - _In_ ID3D12Device* device, - ResourceUploadBatch& resourceUploadBatch, - _In_ ID3D12DescriptorHeap* descriptorHeap) noexcept(false); - - EffectTextureFactory( - _In_ ID3D12Device* device, - ResourceUploadBatch& resourceUploadBatch, - _In_ size_t numDescriptors, - _In_ D3D12_DESCRIPTOR_HEAP_FLAGS descriptorHeapFlags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE) noexcept(false); - - EffectTextureFactory(EffectTextureFactory&&) noexcept; - EffectTextureFactory& operator= (EffectTextureFactory&&) noexcept; - - EffectTextureFactory(EffectTextureFactory const&) = delete; - EffectTextureFactory& operator= (EffectTextureFactory const&) = delete; - - ~EffectTextureFactory() override; - - size_t __cdecl CreateTexture(_In_z_ const wchar_t* name, int descriptorIndex) override; - - ID3D12DescriptorHeap* __cdecl Heap() const noexcept; - - // Shorthand accessors for the descriptor heap - D3D12_CPU_DESCRIPTOR_HANDLE __cdecl GetCpuDescriptorHandle(size_t index) const; - D3D12_GPU_DESCRIPTOR_HANDLE __cdecl GetGpuDescriptorHandle(size_t index) const; - - // How many textures are there in this factory? - size_t __cdecl ResourceCount() const noexcept; - - // Get a resource in a specific slot (note: increases reference count on resource) - void __cdecl GetResource(size_t slot, _Out_ ID3D12Resource** resource, _Out_opt_ bool* isCubeMap = nullptr); - - // Settings. - void __cdecl ReleaseCache(); - - void __cdecl SetSharing(bool enabled) noexcept; - - void __cdecl EnableForceSRGB(bool forceSRGB) noexcept; - void __cdecl EnableAutoGenMips(bool generateMips) noexcept; - - void __cdecl SetDirectory(_In_opt_z_ const wchar_t* path) noexcept; - - private: - // Private implementation - class Impl; - - std::unique_ptr pImpl; - }; - - - //---------------------------------------------------------------------------------- - // Abstract interface to factory for sharing effects - class IEffectFactory - { - public: - virtual ~IEffectFactory() = default; - - IEffectFactory(const IEffectFactory&) = delete; - IEffectFactory& operator=(const IEffectFactory&) = delete; - - struct EffectInfo + // Abstract interface for effects which support directional lighting. + class IEffectLights { - std::wstring name; - bool perVertexColor; - bool enableSkinning; - bool enableDualTexture; - bool enableNormalMaps; - bool biasedVertexNormals; - float specularPower; - float alphaValue; - XMFLOAT3 ambientColor; - XMFLOAT3 diffuseColor; - XMFLOAT3 specularColor; - XMFLOAT3 emissiveColor; - int diffuseTextureIndex; - int specularTextureIndex; - int normalTextureIndex; - int emissiveTextureIndex; - int samplerIndex; - int samplerIndex2; + public: + virtual ~IEffectLights() = default; - EffectInfo() noexcept - : perVertexColor(false) - , enableSkinning(false) - , enableDualTexture(false) - , enableNormalMaps(false) - , biasedVertexNormals(false) - , specularPower(0) - , alphaValue(0) - , ambientColor(0, 0, 0) - , diffuseColor(0, 0, 0) - , specularColor(0, 0, 0) - , emissiveColor(0, 0, 0) - , diffuseTextureIndex(-1) - , specularTextureIndex(-1) - , normalTextureIndex(-1) - , emissiveTextureIndex(-1) - , samplerIndex(-1) - , samplerIndex2(-1) + IEffectLights(const IEffectLights&) = delete; + IEffectLights& operator=(const IEffectLights&) = delete; + + virtual void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) = 0; + + virtual void __cdecl SetLightEnabled(int whichLight, bool value) = 0; + virtual void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) = 0; + virtual void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) = 0; + virtual void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) = 0; + + virtual void __cdecl EnableDefaultLighting() = 0; + + static constexpr int MaxDirectionalLights = 3; + + protected: + IEffectLights() = default; + IEffectLights(IEffectLights&&) = default; + IEffectLights& operator=(IEffectLights&&) = default; + }; + + + // Abstract interface for effects which support fog. + class IEffectFog + { + public: + virtual ~IEffectFog() = default; + + IEffectFog(const IEffectFog&) = delete; + IEffectFog& operator=(const IEffectFog&) = delete; + + virtual void __cdecl SetFogStart(float value) = 0; + virtual void __cdecl SetFogEnd(float value) = 0; + virtual void XM_CALLCONV SetFogColor(FXMVECTOR value) = 0; + + protected: + IEffectFog() = default; + IEffectFog(IEffectFog&&) = default; + IEffectFog& operator=(IEffectFog&&) = default; + }; + + + // Abstract interface for effects which support skinning + class IEffectSkinning + { + public: + virtual ~IEffectSkinning() = default; + + IEffectSkinning(const IEffectSkinning&) = delete; + IEffectSkinning& operator=(const IEffectSkinning&) = delete; + + virtual void __cdecl SetBoneTransforms(_In_reads_(count) XMMATRIX const* value, size_t count) = 0; + virtual void __cdecl ResetBoneTransforms() = 0; + + static constexpr int MaxBones = 72; + + protected: + IEffectSkinning() = default; + IEffectSkinning(IEffectSkinning&&) = default; + IEffectSkinning& operator=(IEffectSkinning&&) = default; + }; + + + //------------------------------------------------------------------------------ + namespace EffectFlags + { + constexpr uint32_t None = 0x00; + constexpr uint32_t Fog = 0x01; + constexpr uint32_t Lighting = 0x02; + + constexpr uint32_t PerPixelLighting = 0x04 | Lighting; + // per pixel lighting implies lighting enabled + + constexpr uint32_t VertexColor = 0x08; + constexpr uint32_t Texture = 0x10; + constexpr uint32_t Instancing = 0x20; + + constexpr uint32_t Specular = 0x100; + // enable optional specular/specularMap feature + + constexpr uint32_t Emissive = 0x200; + // enable optional emissive/emissiveMap feature + + constexpr uint32_t Fresnel = 0x400; + // enable optional Fresnel feature + + constexpr uint32_t Velocity = 0x800; + // enable optional velocity feature + + constexpr uint32_t BiasedVertexNormals = 0x10000; + // compressed vertex normals need x2 bias + } + + + //------------------------------------------------------------------------------ + // Built-in shader supports optional texture mapping, vertex coloring, directional lighting, and fog. + class BasicEffect : public IEffect, public IEffectMatrices, public IEffectLights, public IEffectFog + { + public: + BasicEffect(_In_ ID3D12Device* device, uint32_t effectFlags, const EffectPipelineStateDescription& pipelineDescription); + + BasicEffect(BasicEffect&&) noexcept; + BasicEffect& operator= (BasicEffect&&) noexcept; + + BasicEffect(BasicEffect const&) = delete; + BasicEffect& operator= (BasicEffect const&) = delete; + + ~BasicEffect() override; + + // IEffect methods. + void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; + + // Camera settings. + void XM_CALLCONV SetWorld(FXMMATRIX value) override; + void XM_CALLCONV SetView(FXMMATRIX value) override; + void XM_CALLCONV SetProjection(FXMMATRIX value) override; + void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; + + // Material settings. + void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); + void XM_CALLCONV SetEmissiveColor(FXMVECTOR value); + void XM_CALLCONV SetSpecularColor(FXMVECTOR value); + void __cdecl SetSpecularPower(float value); + void __cdecl DisableSpecular(); + void __cdecl SetAlpha(float value); + void XM_CALLCONV SetColorAndAlpha(FXMVECTOR value); + + // Light settings. + void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) override; + + void __cdecl SetLightEnabled(int whichLight, bool value) override; + void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) override; + void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) override; + void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) override; + + void __cdecl EnableDefaultLighting() override; + + // Fog settings. + void __cdecl SetFogStart(float value) override; + void __cdecl SetFogEnd(float value) override; + void XM_CALLCONV SetFogColor(FXMVECTOR value) override; + + // Texture setting. + void __cdecl SetTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; + + + // Built-in shader supports per-pixel alpha testing. + class AlphaTestEffect : public IEffect, public IEffectMatrices, public IEffectFog + { + public: + AlphaTestEffect(_In_ ID3D12Device* device, uint32_t effectFlags, + const EffectPipelineStateDescription& pipelineDescription, + D3D12_COMPARISON_FUNC alphaFunction = D3D12_COMPARISON_FUNC_GREATER); + + AlphaTestEffect(AlphaTestEffect&&) noexcept; + AlphaTestEffect& operator= (AlphaTestEffect&&) noexcept; + + AlphaTestEffect(AlphaTestEffect const&) = delete; + AlphaTestEffect& operator= (AlphaTestEffect const&) = delete; + + ~AlphaTestEffect() override; + + // IEffect methods. + void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; + + // Camera settings. + void XM_CALLCONV SetWorld(FXMMATRIX value) override; + void XM_CALLCONV SetView(FXMMATRIX value) override; + void XM_CALLCONV SetProjection(FXMMATRIX value) override; + void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; + + // Material settings. + void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); + void __cdecl SetAlpha(float value); + void XM_CALLCONV SetColorAndAlpha(FXMVECTOR value); + + // Fog settings. + void __cdecl SetFogStart(float value) override; + void __cdecl SetFogEnd(float value) override; + void XM_CALLCONV SetFogColor(FXMVECTOR value) override; + + // Texture setting. + void __cdecl SetTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); + + // Alpha test settings. + void __cdecl SetReferenceAlpha(int value); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; + + + // Built-in shader supports two layer multitexturing (eg. for lightmaps or detail textures). + class DualTextureEffect : public IEffect, public IEffectMatrices, public IEffectFog + { + public: + DualTextureEffect(_In_ ID3D12Device* device, uint32_t effectFlags, + const EffectPipelineStateDescription& pipelineDescription); + + DualTextureEffect(DualTextureEffect&&) noexcept; + DualTextureEffect& operator= (DualTextureEffect&&) noexcept; + + DualTextureEffect(DualTextureEffect const&) = delete; + DualTextureEffect& operator= (DualTextureEffect const&) = delete; + + ~DualTextureEffect() override; + + // IEffect methods. + void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; + + // Camera settings. + void XM_CALLCONV SetWorld(FXMMATRIX value) override; + void XM_CALLCONV SetView(FXMMATRIX value) override; + void XM_CALLCONV SetProjection(FXMMATRIX value) override; + void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; + + // Material settings. + void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); + void __cdecl SetAlpha(float value); + void XM_CALLCONV SetColorAndAlpha(FXMVECTOR value); + + // Fog settings. + void __cdecl SetFogStart(float value) override; + void __cdecl SetFogEnd(float value) override; + void XM_CALLCONV SetFogColor(FXMVECTOR value) override; + + // Texture settings. + void __cdecl SetTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); + void __cdecl SetTexture2(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; + + + // Built-in shader supports cubic environment mapping. + class EnvironmentMapEffect : public IEffect, public IEffectMatrices, public IEffectLights, public IEffectFog + { + public: + enum Mapping + { + Mapping_Cube = 0, // Cubic environment map + Mapping_Sphere, // Spherical environment map + Mapping_DualParabola, // Dual-parabola environment map (requires Feature Level 10.0) + }; + + EnvironmentMapEffect(_In_ ID3D12Device* device, uint32_t effectFlags, + const EffectPipelineStateDescription& pipelineDescription, + Mapping mapping = Mapping_Cube); + + EnvironmentMapEffect(EnvironmentMapEffect&&) noexcept; + EnvironmentMapEffect& operator= (EnvironmentMapEffect&&) noexcept; + + EnvironmentMapEffect(EnvironmentMapEffect const&) = delete; + EnvironmentMapEffect& operator= (EnvironmentMapEffect const&) = delete; + + ~EnvironmentMapEffect() override; + + // IEffect methods. + void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; + + // Camera settings. + void XM_CALLCONV SetWorld(FXMMATRIX value) override; + void XM_CALLCONV SetView(FXMMATRIX value) override; + void XM_CALLCONV SetProjection(FXMMATRIX value) override; + void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; + + // Material settings. + void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); + void XM_CALLCONV SetEmissiveColor(FXMVECTOR value); + void __cdecl SetAlpha(float value); + void XM_CALLCONV SetColorAndAlpha(FXMVECTOR value); + + // Light settings. + void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) override; + + void __cdecl SetLightEnabled(int whichLight, bool value) override; + void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) override; + void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) override; + + void __cdecl EnableDefaultLighting() override; + + // Fog settings. + void __cdecl SetFogStart(float value) override; + void __cdecl SetFogEnd(float value) override; + void XM_CALLCONV SetFogColor(FXMVECTOR value) override; + + // Texture setting. + void __cdecl SetTexture(D3D12_GPU_DESCRIPTOR_HANDLE texture, D3D12_GPU_DESCRIPTOR_HANDLE sampler); + + // Environment map settings. + void __cdecl SetEnvironmentMap(D3D12_GPU_DESCRIPTOR_HANDLE texture, D3D12_GPU_DESCRIPTOR_HANDLE sampler); + void __cdecl SetEnvironmentMapAmount(float value); + void XM_CALLCONV SetEnvironmentMapSpecular(FXMVECTOR value); + void __cdecl SetFresnelFactor(float value); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + + // Unsupported interface methods. + void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) override; + }; + + + // Built-in shader supports skinned animation. + class SkinnedEffect : public IEffect, public IEffectMatrices, public IEffectLights, public IEffectFog, public IEffectSkinning + { + public: + SkinnedEffect(_In_ ID3D12Device* device, uint32_t effectFlags, + const EffectPipelineStateDescription& pipelineDescription); + + SkinnedEffect(SkinnedEffect&&) noexcept; + SkinnedEffect& operator= (SkinnedEffect&&) noexcept; + + SkinnedEffect(SkinnedEffect const&) = delete; + SkinnedEffect& operator= (SkinnedEffect const&) = delete; + + ~SkinnedEffect() override; + + // IEffect methods. + void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; + + // Camera settings. + void XM_CALLCONV SetWorld(FXMMATRIX value) override; + void XM_CALLCONV SetView(FXMMATRIX value) override; + void XM_CALLCONV SetProjection(FXMMATRIX value) override; + void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; + + // Material settings. + void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); + void XM_CALLCONV SetEmissiveColor(FXMVECTOR value); + void XM_CALLCONV SetSpecularColor(FXMVECTOR value); + void __cdecl SetSpecularPower(float value); + void __cdecl DisableSpecular(); + void __cdecl SetAlpha(float value); + void XM_CALLCONV SetColorAndAlpha(FXMVECTOR value); + + // Light settings. + void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) override; + + void __cdecl SetLightEnabled(int whichLight, bool value) override; + void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) override; + void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) override; + void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) override; + + void __cdecl EnableDefaultLighting() override; + + // Fog settings. + void __cdecl SetFogStart(float value) override; + void __cdecl SetFogEnd(float value) override; + void XM_CALLCONV SetFogColor(FXMVECTOR value) override; + + // Texture setting. + void __cdecl SetTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); + + // Animation settings. + void __cdecl SetBoneTransforms(_In_reads_(count) XMMATRIX const* value, size_t count) override; + void __cdecl ResetBoneTransforms() override; + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; + + + //------------------------------------------------------------------------------ + // Built-in shader extends BasicEffect with normal map and optional specular map + class NormalMapEffect : public IEffect, public IEffectMatrices, public IEffectLights, public IEffectFog + { + public: + NormalMapEffect(_In_ ID3D12Device* device, uint32_t effectFlags, + const EffectPipelineStateDescription& pipelineDescription) : + NormalMapEffect(device, effectFlags, pipelineDescription, false) { } + + NormalMapEffect(NormalMapEffect&&) noexcept; + NormalMapEffect& operator= (NormalMapEffect&&) noexcept; + + NormalMapEffect(NormalMapEffect const&) = delete; + NormalMapEffect& operator= (NormalMapEffect const&) = delete; + + ~NormalMapEffect() override; + + // IEffect methods. + void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; + + // Camera settings. + void XM_CALLCONV SetWorld(FXMMATRIX value) override; + void XM_CALLCONV SetView(FXMMATRIX value) override; + void XM_CALLCONV SetProjection(FXMMATRIX value) override; + void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; + + // Material settings. + void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); + void XM_CALLCONV SetEmissiveColor(FXMVECTOR value); + void XM_CALLCONV SetSpecularColor(FXMVECTOR value); + void __cdecl SetSpecularPower(float value); + void __cdecl DisableSpecular(); + void __cdecl SetAlpha(float value); + void XM_CALLCONV SetColorAndAlpha(FXMVECTOR value); + + // Light settings. + void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) override; + + void __cdecl SetLightEnabled(int whichLight, bool value) override; + void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) override; + void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) override; + void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) override; + + void __cdecl EnableDefaultLighting() override; + + // Fog settings. + void __cdecl SetFogStart(float value) override; + void __cdecl SetFogEnd(float value) override; + void XM_CALLCONV SetFogColor(FXMVECTOR value) override; + + // Texture setting - albedo, normal and specular intensity + void __cdecl SetTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); + void __cdecl SetNormalTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); + void __cdecl SetSpecularTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); + + protected: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + + NormalMapEffect(_In_ ID3D12Device* device, uint32_t effectFlags, + const EffectPipelineStateDescription& pipelineDescription, bool skinningEnabled); }; - virtual std::shared_ptr __cdecl CreateEffect( - const EffectInfo& info, - const EffectPipelineStateDescription& opaquePipelineState, - const EffectPipelineStateDescription& alphaPipelineState, - const D3D12_INPUT_LAYOUT_DESC& inputLayout, - int textureDescriptorOffset = 0, - int samplerDescriptorOffset = 0) = 0; + class SkinnedNormalMapEffect : public NormalMapEffect, public IEffectSkinning + { + public: + SkinnedNormalMapEffect(_In_ ID3D12Device* device, uint32_t effectFlags, + const EffectPipelineStateDescription& pipelineDescription) : + NormalMapEffect(device, effectFlags, pipelineDescription, true) + { + } - protected: - IEffectFactory() = default; - IEffectFactory(IEffectFactory&&) = default; - IEffectFactory& operator=(IEffectFactory&&) = default; - }; + SkinnedNormalMapEffect(SkinnedNormalMapEffect&&) = default; + SkinnedNormalMapEffect& operator= (SkinnedNormalMapEffect&&) = default; + + SkinnedNormalMapEffect(SkinnedNormalMapEffect const&) = delete; + SkinnedNormalMapEffect& operator= (SkinnedNormalMapEffect const&) = delete; + + // Animation settings. + void __cdecl SetBoneTransforms(_In_reads_(count) XMMATRIX const* value, size_t count) override; + void __cdecl ResetBoneTransforms() override; + }; - // Factory for sharing effects - class EffectFactory : public IEffectFactory - { - public: - EffectFactory(_In_ ID3D12Device* device); - EffectFactory( - _In_ ID3D12DescriptorHeap* textureDescriptors, - _In_ ID3D12DescriptorHeap* samplerDescriptors); + //------------------------------------------------------------------------------ + // Built-in shader for Physically-Based Rendering (Roughness/Metalness) with Image-based lighting + class PBREffect : public IEffect, public IEffectMatrices, public IEffectLights + { + public: + PBREffect(_In_ ID3D12Device* device, uint32_t effectFlags, + const EffectPipelineStateDescription& pipelineDescription) : + PBREffect(device, effectFlags, pipelineDescription, false) + { + } - EffectFactory(EffectFactory&&) noexcept; - EffectFactory& operator= (EffectFactory&&) noexcept; + PBREffect(PBREffect&&) noexcept; + PBREffect& operator= (PBREffect&&) noexcept; - EffectFactory(EffectFactory const&) = delete; - EffectFactory& operator= (EffectFactory const&) = delete; + PBREffect(PBREffect const&) = delete; + PBREffect& operator= (PBREffect const&) = delete; - ~EffectFactory() override; + ~PBREffect() override; - // IEffectFactory methods. - virtual std::shared_ptr __cdecl CreateEffect( - const EffectInfo& info, - const EffectPipelineStateDescription& opaquePipelineState, - const EffectPipelineStateDescription& alphaPipelineState, - const D3D12_INPUT_LAYOUT_DESC& inputLayout, - int textureDescriptorOffset = 0, - int samplerDescriptorOffset = 0) override; + // IEffect methods. + void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; - // Settings. - void __cdecl ReleaseCache(); + // Camera settings. + void XM_CALLCONV SetWorld(FXMMATRIX value) override; + void XM_CALLCONV SetView(FXMMATRIX value) override; + void XM_CALLCONV SetProjection(FXMMATRIX value) override; + void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; - void __cdecl SetSharing(bool enabled) noexcept; + // Light settings. + void __cdecl SetLightEnabled(int whichLight, bool value) override; + void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) override; + void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) override; - void __cdecl EnablePerPixelLighting(bool enabled) noexcept; + void __cdecl EnableDefaultLighting() override; - void __cdecl EnableNormalMapEffect(bool enabled) noexcept; + // PBR Settings. + void __cdecl SetAlpha(float value); + void XM_CALLCONV SetConstantAlbedo(FXMVECTOR value); + void __cdecl SetConstantMetallic(float value); + void __cdecl SetConstantRoughness(float value); - void __cdecl EnableFogging(bool enabled) noexcept; + // Texture settings. + void __cdecl SetAlbedoTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); + void __cdecl SetNormalTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); + void __cdecl SetRMATexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); - void __cdecl EnableInstancing(bool enabled) noexcept; + void __cdecl SetEmissiveTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); - private: - // Private implementation. - class Impl; + void __cdecl SetSurfaceTextures( + D3D12_GPU_DESCRIPTOR_HANDLE albedo, + D3D12_GPU_DESCRIPTOR_HANDLE normal, + D3D12_GPU_DESCRIPTOR_HANDLE roughnessMetallicAmbientOcclusion, + D3D12_GPU_DESCRIPTOR_HANDLE sampler); - std::shared_ptr pImpl; - }; + void __cdecl SetIBLTextures( + D3D12_GPU_DESCRIPTOR_HANDLE radiance, + int numRadianceMips, + D3D12_GPU_DESCRIPTOR_HANDLE irradiance, + D3D12_GPU_DESCRIPTOR_HANDLE sampler); + + // Render target size, required for velocity buffer output. + void __cdecl SetRenderTargetSizeInPixels(int width, int height); + + protected: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + + PBREffect(_In_ ID3D12Device* device, uint32_t effectFlags, + const EffectPipelineStateDescription& pipelineDescription, bool skinningEnabled); + + // Unsupported interface methods. + void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) override; + void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) override; + }; + + class SkinnedPBREffect : public PBREffect, public IEffectSkinning + { + public: + SkinnedPBREffect(_In_ ID3D12Device* device, uint32_t effectFlags, + const EffectPipelineStateDescription& pipelineDescription) : + PBREffect(device, effectFlags, pipelineDescription, true) + { + } + + SkinnedPBREffect(SkinnedPBREffect&&) = default; + SkinnedPBREffect& operator= (SkinnedPBREffect&&) = default; + + SkinnedPBREffect(SkinnedPBREffect const&) = delete; + SkinnedPBREffect& operator= (SkinnedPBREffect const&) = delete; + + // Animation settings. + void __cdecl SetBoneTransforms(_In_reads_(count) XMMATRIX const* value, size_t count) override; + void __cdecl ResetBoneTransforms() override; + }; - // Factory for Physically Based Rendering (PBR) - class PBREffectFactory : public IEffectFactory - { - public: - PBREffectFactory(_In_ ID3D12Device* device) noexcept(false); - PBREffectFactory( - _In_ ID3D12DescriptorHeap* textureDescriptors, - _In_ ID3D12DescriptorHeap* samplerDescriptors) noexcept(false); + //------------------------------------------------------------------------------ + // Built-in shader for debug visualization of normals, tangents, etc. + class DebugEffect : public IEffect, public IEffectMatrices + { + public: + enum Mode + { + Mode_Default = 0, // Hemispherical ambient lighting + Mode_Normals, // RGB normals + Mode_Tangents, // RGB tangents + Mode_BiTangents, // RGB bi-tangents + }; - PBREffectFactory(PBREffectFactory&&) noexcept; - PBREffectFactory& operator= (PBREffectFactory&&) noexcept; + DebugEffect(_In_ ID3D12Device* device, uint32_t effectFlags, + const EffectPipelineStateDescription& pipelineDescription, + Mode debugMode = Mode_Default); - PBREffectFactory(PBREffectFactory const&) = delete; - PBREffectFactory& operator= (PBREffectFactory const&) = delete; + DebugEffect(DebugEffect&&) noexcept; + DebugEffect& operator= (DebugEffect&&) noexcept; - ~PBREffectFactory() override; + DebugEffect(DebugEffect const&) = delete; + DebugEffect& operator= (DebugEffect const&) = delete; - // IEffectFactory methods. - virtual std::shared_ptr __cdecl CreateEffect( - const EffectInfo& info, - const EffectPipelineStateDescription& opaquePipelineState, - const EffectPipelineStateDescription& alphaPipelineState, - const D3D12_INPUT_LAYOUT_DESC& inputLayout, - int textureDescriptorOffset = 0, - int samplerDescriptorOffset = 0) override; + ~DebugEffect() override; - // Settings. - void __cdecl ReleaseCache(); + // IEffect methods. + void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; - void __cdecl SetSharing(bool enabled) noexcept; + // Camera settings. + void XM_CALLCONV SetWorld(FXMMATRIX value) override; + void XM_CALLCONV SetView(FXMMATRIX value) override; + void XM_CALLCONV SetProjection(FXMMATRIX value) override; + void XM_CALLCONV SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection) override; - void __cdecl EnableInstancing(bool enabled) noexcept; + // Debug Settings. + void XM_CALLCONV SetHemisphericalAmbientColor(FXMVECTOR upper, FXMVECTOR lower); + void __cdecl SetAlpha(float value); - private: - // Private implementation. - class Impl; + private: + // Private implementation. + class Impl; - std::shared_ptr pImpl; - }; + std::unique_ptr pImpl; + }; + + + //------------------------------------------------------------------------------ + // Abstract interface to factory texture resources + class IEffectTextureFactory + { + public: + virtual ~IEffectTextureFactory() = default; + + IEffectTextureFactory(const IEffectTextureFactory&) = delete; + IEffectTextureFactory& operator=(const IEffectTextureFactory&) = delete; + + virtual size_t __cdecl CreateTexture(_In_z_ const wchar_t* name, int descriptorIndex) = 0; + + protected: + IEffectTextureFactory() = default; + IEffectTextureFactory(IEffectTextureFactory&&) = default; + IEffectTextureFactory& operator=(IEffectTextureFactory&&) = default; + }; + + + // Factory for sharing texture resources + class EffectTextureFactory : public IEffectTextureFactory + { + public: + EffectTextureFactory( + _In_ ID3D12Device* device, + ResourceUploadBatch& resourceUploadBatch, + _In_ ID3D12DescriptorHeap* descriptorHeap) noexcept(false); + + EffectTextureFactory( + _In_ ID3D12Device* device, + ResourceUploadBatch& resourceUploadBatch, + _In_ size_t numDescriptors, + _In_ D3D12_DESCRIPTOR_HEAP_FLAGS descriptorHeapFlags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE) noexcept(false); + + EffectTextureFactory(EffectTextureFactory&&) noexcept; + EffectTextureFactory& operator= (EffectTextureFactory&&) noexcept; + + EffectTextureFactory(EffectTextureFactory const&) = delete; + EffectTextureFactory& operator= (EffectTextureFactory const&) = delete; + + ~EffectTextureFactory() override; + + size_t __cdecl CreateTexture(_In_z_ const wchar_t* name, int descriptorIndex) override; + + ID3D12DescriptorHeap* __cdecl Heap() const noexcept; + + // Shorthand accessors for the descriptor heap + D3D12_CPU_DESCRIPTOR_HANDLE __cdecl GetCpuDescriptorHandle(size_t index) const; + D3D12_GPU_DESCRIPTOR_HANDLE __cdecl GetGpuDescriptorHandle(size_t index) const; + + // How many textures are there in this factory? + size_t __cdecl ResourceCount() const noexcept; + + // Get a resource in a specific slot (note: increases reference count on resource) + void __cdecl GetResource(size_t slot, _Out_ ID3D12Resource** resource, _Out_opt_ bool* isCubeMap = nullptr); + + // Settings. + void __cdecl ReleaseCache(); + + void __cdecl SetSharing(bool enabled) noexcept; + + void __cdecl EnableForceSRGB(bool forceSRGB) noexcept; + void __cdecl EnableAutoGenMips(bool generateMips) noexcept; + + void __cdecl SetDirectory(_In_opt_z_ const wchar_t* path) noexcept; + + private: + // Private implementation + class Impl; + + std::unique_ptr pImpl; + }; + + + //------------------------------------------------------------------------------ + // Abstract interface to factory for sharing effects + class IEffectFactory + { + public: + virtual ~IEffectFactory() = default; + + IEffectFactory(const IEffectFactory&) = delete; + IEffectFactory& operator=(const IEffectFactory&) = delete; + + struct EffectInfo + { + std::wstring name; + bool perVertexColor; + bool enableSkinning; + bool enableDualTexture; + bool enableNormalMaps; + bool biasedVertexNormals; + float specularPower; + float alphaValue; + XMFLOAT3 ambientColor; + XMFLOAT3 diffuseColor; + XMFLOAT3 specularColor; + XMFLOAT3 emissiveColor; + int diffuseTextureIndex; + int specularTextureIndex; + int normalTextureIndex; + int emissiveTextureIndex; + int samplerIndex; + int samplerIndex2; + + EffectInfo() noexcept + : perVertexColor(false) + , enableSkinning(false) + , enableDualTexture(false) + , enableNormalMaps(false) + , biasedVertexNormals(false) + , specularPower(0) + , alphaValue(0) + , ambientColor(0, 0, 0) + , diffuseColor(0, 0, 0) + , specularColor(0, 0, 0) + , emissiveColor(0, 0, 0) + , diffuseTextureIndex(-1) + , specularTextureIndex(-1) + , normalTextureIndex(-1) + , emissiveTextureIndex(-1) + , samplerIndex(-1) + , samplerIndex2(-1) + { + } + }; + + virtual std::shared_ptr __cdecl CreateEffect( + const EffectInfo& info, + const EffectPipelineStateDescription& opaquePipelineState, + const EffectPipelineStateDescription& alphaPipelineState, + const D3D12_INPUT_LAYOUT_DESC& inputLayout, + int textureDescriptorOffset = 0, + int samplerDescriptorOffset = 0) = 0; + + protected: + IEffectFactory() = default; + IEffectFactory(IEffectFactory&&) = default; + IEffectFactory& operator=(IEffectFactory&&) = default; + }; + + + // Factory for sharing effects + class EffectFactory : public IEffectFactory + { + public: + EffectFactory(_In_ ID3D12Device* device); + EffectFactory( + _In_ ID3D12DescriptorHeap* textureDescriptors, + _In_ ID3D12DescriptorHeap* samplerDescriptors); + + EffectFactory(EffectFactory&&) noexcept; + EffectFactory& operator= (EffectFactory&&) noexcept; + + EffectFactory(EffectFactory const&) = delete; + EffectFactory& operator= (EffectFactory const&) = delete; + + ~EffectFactory() override; + + // IEffectFactory methods. + virtual std::shared_ptr __cdecl CreateEffect( + const EffectInfo& info, + const EffectPipelineStateDescription& opaquePipelineState, + const EffectPipelineStateDescription& alphaPipelineState, + const D3D12_INPUT_LAYOUT_DESC& inputLayout, + int textureDescriptorOffset = 0, + int samplerDescriptorOffset = 0) override; + + // Settings. + void __cdecl ReleaseCache(); + + void __cdecl SetSharing(bool enabled) noexcept; + + void __cdecl EnablePerPixelLighting(bool enabled) noexcept; + + void __cdecl EnableNormalMapEffect(bool enabled) noexcept; + + void __cdecl EnableFogging(bool enabled) noexcept; + + void __cdecl EnableInstancing(bool enabled) noexcept; + + private: + // Private implementation. + class Impl; + + std::shared_ptr pImpl; + }; + + + // Factory for Physically Based Rendering (PBR) + class PBREffectFactory : public IEffectFactory + { + public: + PBREffectFactory(_In_ ID3D12Device* device) noexcept(false); + PBREffectFactory( + _In_ ID3D12DescriptorHeap* textureDescriptors, + _In_ ID3D12DescriptorHeap* samplerDescriptors) noexcept(false); + + PBREffectFactory(PBREffectFactory&&) noexcept; + PBREffectFactory& operator= (PBREffectFactory&&) noexcept; + + PBREffectFactory(PBREffectFactory const&) = delete; + PBREffectFactory& operator= (PBREffectFactory const&) = delete; + + ~PBREffectFactory() override; + + // IEffectFactory methods. + virtual std::shared_ptr __cdecl CreateEffect( + const EffectInfo& info, + const EffectPipelineStateDescription& opaquePipelineState, + const EffectPipelineStateDescription& alphaPipelineState, + const D3D12_INPUT_LAYOUT_DESC& inputLayout, + int textureDescriptorOffset = 0, + int samplerDescriptorOffset = 0) override; + + // Settings. + void __cdecl ReleaseCache(); + + void __cdecl SetSharing(bool enabled) noexcept; + + void __cdecl EnableInstancing(bool enabled) noexcept; + + private: + // Private implementation. + class Impl; + + std::shared_ptr pImpl; + }; + } } diff --git a/Kits/DirectXTK12/Inc/GeometricPrimitive.h b/Kits/DirectXTK12/Inc/GeometricPrimitive.h index 9699b6e..fa303ff 100644 --- a/Kits/DirectXTK12/Inc/GeometricPrimitive.h +++ b/Kits/DirectXTK12/Inc/GeometricPrimitive.h @@ -19,76 +19,80 @@ namespace DirectX { - class IEffect; class ResourceUploadBatch; - class GeometricPrimitive + inline namespace DX12 { - public: - GeometricPrimitive(GeometricPrimitive&&) = default; - GeometricPrimitive& operator= (GeometricPrimitive&&) = default; + class IEffect; - GeometricPrimitive(GeometricPrimitive const&) = delete; - GeometricPrimitive& operator= (GeometricPrimitive const&) = delete; + class GeometricPrimitive + { + public: + GeometricPrimitive(GeometricPrimitive&&) = default; + GeometricPrimitive& operator= (GeometricPrimitive&&) = default; - virtual ~GeometricPrimitive(); + GeometricPrimitive(GeometricPrimitive const&) = delete; + GeometricPrimitive& operator= (GeometricPrimitive const&) = delete; - using VertexType = VertexPositionNormalTexture; - using VertexCollection = std::vector; - using IndexCollection = std::vector; + virtual ~GeometricPrimitive(); - // Factory methods. - static std::unique_ptr __cdecl CreateCube(float size = 1, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); - static std::unique_ptr __cdecl CreateBox(const XMFLOAT3& size, bool rhcoords = true, bool invertn = false, _In_opt_ ID3D12Device* device = nullptr); - static std::unique_ptr __cdecl CreateSphere(float diameter = 1, size_t tessellation = 16, bool rhcoords = true, bool invertn = false, _In_opt_ ID3D12Device* device = nullptr); - static std::unique_ptr __cdecl CreateGeoSphere(float diameter = 1, size_t tessellation = 3, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); - static std::unique_ptr __cdecl CreateCylinder(float height = 1, float diameter = 1, size_t tessellation = 32, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); - static std::unique_ptr __cdecl CreateCone(float diameter = 1, float height = 1, size_t tessellation = 32, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); - static std::unique_ptr __cdecl CreateTorus(float diameter = 1, float thickness = 0.333f, size_t tessellation = 32, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); - static std::unique_ptr __cdecl CreateTetrahedron(float size = 1, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); - static std::unique_ptr __cdecl CreateOctahedron(float size = 1, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); - static std::unique_ptr __cdecl CreateDodecahedron(float size = 1, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); - static std::unique_ptr __cdecl CreateIcosahedron(float size = 1, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); - static std::unique_ptr __cdecl CreateTeapot(float size = 1, size_t tessellation = 8, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); - static std::unique_ptr __cdecl CreateCustom(const VertexCollection& vertices, const IndexCollection& indices, _In_opt_ ID3D12Device* device = nullptr); + using VertexType = VertexPositionNormalTexture; + using VertexCollection = std::vector; + using IndexCollection = std::vector; - static void __cdecl CreateCube(VertexCollection& vertices, IndexCollection& indices, float size = 1, bool rhcoords = true); - static void __cdecl CreateBox(VertexCollection& vertices, IndexCollection& indices, const XMFLOAT3& size, bool rhcoords = true, bool invertn = false); - static void __cdecl CreateSphere(VertexCollection& vertices, IndexCollection& indices, float diameter = 1, size_t tessellation = 16, bool rhcoords = true, bool invertn = false); - static void __cdecl CreateGeoSphere(VertexCollection& vertices, IndexCollection& indices, float diameter = 1, size_t tessellation = 3, bool rhcoords = true); - static void __cdecl CreateCylinder(VertexCollection& vertices, IndexCollection& indices, float height = 1, float diameter = 1, size_t tessellation = 32, bool rhcoords = true); - static void __cdecl CreateCone(VertexCollection& vertices, IndexCollection& indices, float diameter = 1, float height = 1, size_t tessellation = 32, bool rhcoords = true); - static void __cdecl CreateTorus(VertexCollection& vertices, IndexCollection& indices, float diameter = 1, float thickness = 0.333f, size_t tessellation = 32, bool rhcoords = true); - static void __cdecl CreateTetrahedron(VertexCollection& vertices, IndexCollection& indices, float size = 1, bool rhcoords = true); - static void __cdecl CreateOctahedron(VertexCollection& vertices, IndexCollection& indices, float size = 1, bool rhcoords = true); - static void __cdecl CreateDodecahedron(VertexCollection& vertices, IndexCollection& indices, float size = 1, bool rhcoords = true); - static void __cdecl CreateIcosahedron(VertexCollection& vertices, IndexCollection& indices, float size = 1, bool rhcoords = true); - static void __cdecl CreateTeapot(VertexCollection& vertices, IndexCollection& indices, float size = 1, size_t tessellation = 8, bool rhcoords = true); + // Factory methods. + static std::unique_ptr __cdecl CreateCube(float size = 1, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); + static std::unique_ptr __cdecl CreateBox(const XMFLOAT3& size, bool rhcoords = true, bool invertn = false, _In_opt_ ID3D12Device* device = nullptr); + static std::unique_ptr __cdecl CreateSphere(float diameter = 1, size_t tessellation = 16, bool rhcoords = true, bool invertn = false, _In_opt_ ID3D12Device* device = nullptr); + static std::unique_ptr __cdecl CreateGeoSphere(float diameter = 1, size_t tessellation = 3, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); + static std::unique_ptr __cdecl CreateCylinder(float height = 1, float diameter = 1, size_t tessellation = 32, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); + static std::unique_ptr __cdecl CreateCone(float diameter = 1, float height = 1, size_t tessellation = 32, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); + static std::unique_ptr __cdecl CreateTorus(float diameter = 1, float thickness = 0.333f, size_t tessellation = 32, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); + static std::unique_ptr __cdecl CreateTetrahedron(float size = 1, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); + static std::unique_ptr __cdecl CreateOctahedron(float size = 1, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); + static std::unique_ptr __cdecl CreateDodecahedron(float size = 1, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); + static std::unique_ptr __cdecl CreateIcosahedron(float size = 1, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); + static std::unique_ptr __cdecl CreateTeapot(float size = 1, size_t tessellation = 8, bool rhcoords = true, _In_opt_ ID3D12Device* device = nullptr); + static std::unique_ptr __cdecl CreateCustom(const VertexCollection& vertices, const IndexCollection& indices, _In_opt_ ID3D12Device* device = nullptr); - // Load VB/IB resources for static geometry. - void __cdecl LoadStaticBuffers( - _In_ ID3D12Device* device, - ResourceUploadBatch& resourceUploadBatch); + static void __cdecl CreateCube(VertexCollection& vertices, IndexCollection& indices, float size = 1, bool rhcoords = true); + static void __cdecl CreateBox(VertexCollection& vertices, IndexCollection& indices, const XMFLOAT3& size, bool rhcoords = true, bool invertn = false); + static void __cdecl CreateSphere(VertexCollection& vertices, IndexCollection& indices, float diameter = 1, size_t tessellation = 16, bool rhcoords = true, bool invertn = false); + static void __cdecl CreateGeoSphere(VertexCollection& vertices, IndexCollection& indices, float diameter = 1, size_t tessellation = 3, bool rhcoords = true); + static void __cdecl CreateCylinder(VertexCollection& vertices, IndexCollection& indices, float height = 1, float diameter = 1, size_t tessellation = 32, bool rhcoords = true); + static void __cdecl CreateCone(VertexCollection& vertices, IndexCollection& indices, float diameter = 1, float height = 1, size_t tessellation = 32, bool rhcoords = true); + static void __cdecl CreateTorus(VertexCollection& vertices, IndexCollection& indices, float diameter = 1, float thickness = 0.333f, size_t tessellation = 32, bool rhcoords = true); + static void __cdecl CreateTetrahedron(VertexCollection& vertices, IndexCollection& indices, float size = 1, bool rhcoords = true); + static void __cdecl CreateOctahedron(VertexCollection& vertices, IndexCollection& indices, float size = 1, bool rhcoords = true); + static void __cdecl CreateDodecahedron(VertexCollection& vertices, IndexCollection& indices, float size = 1, bool rhcoords = true); + static void __cdecl CreateIcosahedron(VertexCollection& vertices, IndexCollection& indices, float size = 1, bool rhcoords = true); + static void __cdecl CreateTeapot(VertexCollection& vertices, IndexCollection& indices, float size = 1, size_t tessellation = 8, bool rhcoords = true); - // Transition VB/IB resources for static geometry. - void __cdecl Transition( - _In_ ID3D12GraphicsCommandList* commandList, - D3D12_RESOURCE_STATES stateBeforeVB, - D3D12_RESOURCE_STATES stateAfterVB, - D3D12_RESOURCE_STATES stateBeforeIB, - D3D12_RESOURCE_STATES stateAfterIB); + // Load VB/IB resources for static geometry. + void __cdecl LoadStaticBuffers( + _In_ ID3D12Device* device, + ResourceUploadBatch& resourceUploadBatch); - // Draw the primitive. - void __cdecl Draw(_In_ ID3D12GraphicsCommandList* commandList) const; + // Transition VB/IB resources for static geometry. + void __cdecl Transition( + _In_ ID3D12GraphicsCommandList* commandList, + D3D12_RESOURCE_STATES stateBeforeVB, + D3D12_RESOURCE_STATES stateAfterVB, + D3D12_RESOURCE_STATES stateBeforeIB, + D3D12_RESOURCE_STATES stateAfterIB); - void __cdecl DrawInstanced(_In_ ID3D12GraphicsCommandList* commandList, uint32_t instanceCount, uint32_t startInstanceLocation = 0) const; + // Draw the primitive. + void __cdecl Draw(_In_ ID3D12GraphicsCommandList* commandList) const; - private: - GeometricPrimitive() noexcept(false); + void __cdecl DrawInstanced(_In_ ID3D12GraphicsCommandList* commandList, uint32_t instanceCount, uint32_t startInstanceLocation = 0) const; - // Private implementation. - class Impl; + private: + GeometricPrimitive() noexcept(false); - std::unique_ptr pImpl; - }; + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; + } } diff --git a/Kits/DirectXTK12/Inc/GraphicsMemory.h b/Kits/DirectXTK12/Inc/GraphicsMemory.h index d720c4a..25750a3 100644 --- a/Kits/DirectXTK12/Inc/GraphicsMemory.h +++ b/Kits/DirectXTK12/Inc/GraphicsMemory.h @@ -29,155 +29,158 @@ namespace DirectX { class LinearAllocatorPage; + inline namespace DX12 + { // Works a little like a smart pointer. The memory will only be fenced by the GPU once the pointer // has been invalidated or the user explicitly marks it for fencing. - class GraphicsResource - { - public: - GraphicsResource() noexcept; - GraphicsResource( - _In_ LinearAllocatorPage* page, - _In_ D3D12_GPU_VIRTUAL_ADDRESS gpuAddress, - _In_ ID3D12Resource* resource, - _In_ void* memory, - _In_ size_t offset, - _In_ size_t size) noexcept; - - GraphicsResource(GraphicsResource&& other) noexcept; - GraphicsResource&& operator= (GraphicsResource&&) noexcept; - - GraphicsResource(const GraphicsResource&) = delete; - GraphicsResource& operator= (const GraphicsResource&) = delete; - - ~GraphicsResource(); - - D3D12_GPU_VIRTUAL_ADDRESS GpuAddress() const noexcept { return mGpuAddress; } - ID3D12Resource* Resource() const noexcept { return mResource; } - void* Memory() const noexcept { return mMemory; } - size_t ResourceOffset() const noexcept { return mBufferOffset; } - size_t Size() const noexcept { return mSize; } - - explicit operator bool() const noexcept { return mResource != nullptr; } - - // Clear the pointer. Using operator -> will produce bad results. - void __cdecl Reset() noexcept; - void __cdecl Reset(GraphicsResource&&) noexcept; - - private: - LinearAllocatorPage* mPage; - D3D12_GPU_VIRTUAL_ADDRESS mGpuAddress; - ID3D12Resource* mResource; - void* mMemory; - size_t mBufferOffset; - size_t mSize; - }; - - class SharedGraphicsResource - { - public: - SharedGraphicsResource() noexcept; - - SharedGraphicsResource(SharedGraphicsResource&&) noexcept; - SharedGraphicsResource&& operator= (SharedGraphicsResource&&) noexcept; - - SharedGraphicsResource(GraphicsResource&&); - SharedGraphicsResource&& operator= (GraphicsResource&&); - - SharedGraphicsResource(const SharedGraphicsResource&) noexcept; - SharedGraphicsResource& operator= (const SharedGraphicsResource&) noexcept; - - SharedGraphicsResource(const GraphicsResource&) = delete; - SharedGraphicsResource& operator= (const GraphicsResource&) = delete; - - ~SharedGraphicsResource(); - - D3D12_GPU_VIRTUAL_ADDRESS GpuAddress() const noexcept { return mSharedResource->GpuAddress(); } - ID3D12Resource* Resource() const noexcept { return mSharedResource->Resource(); } - void* Memory() const noexcept { return mSharedResource->Memory(); } - size_t ResourceOffset() const noexcept { return mSharedResource->ResourceOffset(); } - size_t Size() const noexcept { return mSharedResource->Size(); } - - explicit operator bool() const noexcept { return mSharedResource != nullptr; } - - bool operator == (const SharedGraphicsResource& other) const noexcept { return mSharedResource.get() == other.mSharedResource.get(); } - bool operator != (const SharedGraphicsResource& other) const noexcept { return mSharedResource.get() != other.mSharedResource.get(); } - - // Clear the pointer. Using operator -> will produce bad results. - void __cdecl Reset() noexcept; - void __cdecl Reset(GraphicsResource&&); - void __cdecl Reset(SharedGraphicsResource&&) noexcept; - void __cdecl Reset(const SharedGraphicsResource& resource) noexcept; - - private: - std::shared_ptr mSharedResource; - }; - - //---------------------------------------------------------------------------------- - struct GraphicsMemoryStatistics - { - size_t committedMemory; // Bytes of memory currently committed/in-flight - size_t totalMemory; // Total bytes of memory used by the allocators - size_t totalPages; // Total page count - size_t peakCommitedMemory; // Peak commited memory value since last reset - size_t peakTotalMemory; // Peak total bytes - size_t peakTotalPages; // Peak total page count - }; - - //---------------------------------------------------------------------------------- - class GraphicsMemory - { - public: - explicit GraphicsMemory(_In_ ID3D12Device* device); - - GraphicsMemory(GraphicsMemory&&) noexcept; - GraphicsMemory& operator= (GraphicsMemory&&) noexcept; - - GraphicsMemory(GraphicsMemory const&) = delete; - GraphicsMemory& operator=(GraphicsMemory const&) = delete; - - virtual ~GraphicsMemory(); - - // Make sure to keep the GraphicsResource handle alive as long as you need to access - // the memory on the CPU. For example, do not simply cache GpuAddress() and discard - // the GraphicsResource object, or your memory may be overwritten later. - GraphicsResource __cdecl Allocate(size_t size, size_t alignment = 16); - - // Special overload of Allocate that aligns to D3D12 constant buffer alignment requirements - template GraphicsResource AllocateConstant() + class GraphicsResource { - constexpr size_t alignment = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT; - constexpr size_t alignedSize = (sizeof(T) + alignment - 1) & ~(alignment - 1); - return Allocate(alignedSize, alignment); - } - template GraphicsResource AllocateConstant(const T& setData) + public: + GraphicsResource() noexcept; + GraphicsResource( + _In_ LinearAllocatorPage* page, + _In_ D3D12_GPU_VIRTUAL_ADDRESS gpuAddress, + _In_ ID3D12Resource* resource, + _In_ void* memory, + _In_ size_t offset, + _In_ size_t size) noexcept; + + GraphicsResource(GraphicsResource&& other) noexcept; + GraphicsResource&& operator= (GraphicsResource&&) noexcept; + + GraphicsResource(const GraphicsResource&) = delete; + GraphicsResource& operator= (const GraphicsResource&) = delete; + + ~GraphicsResource(); + + D3D12_GPU_VIRTUAL_ADDRESS GpuAddress() const noexcept { return mGpuAddress; } + ID3D12Resource* Resource() const noexcept { return mResource; } + void* Memory() const noexcept { return mMemory; } + size_t ResourceOffset() const noexcept { return mBufferOffset; } + size_t Size() const noexcept { return mSize; } + + explicit operator bool() const noexcept { return mResource != nullptr; } + + // Clear the pointer. Using operator -> will produce bad results. + void __cdecl Reset() noexcept; + void __cdecl Reset(GraphicsResource&&) noexcept; + + private: + LinearAllocatorPage* mPage; + D3D12_GPU_VIRTUAL_ADDRESS mGpuAddress; + ID3D12Resource* mResource; + void* mMemory; + size_t mBufferOffset; + size_t mSize; + }; + + class SharedGraphicsResource { - GraphicsResource alloc = AllocateConstant(); - memcpy(alloc.Memory(), &setData, sizeof(T)); - return alloc; - } + public: + SharedGraphicsResource() noexcept; - // Submits all the pending one-shot memory to the GPU. - // The memory will be recycled once the GPU is done with it. - void __cdecl Commit(_In_ ID3D12CommandQueue* commandQueue); + SharedGraphicsResource(SharedGraphicsResource&&) noexcept; + SharedGraphicsResource&& operator= (SharedGraphicsResource&&) noexcept; - // This frees up any unused memory. - // If you want to make sure all memory is reclaimed, idle the GPU before calling this. - // It is not recommended that you call this unless absolutely necessary (e.g. your - // memory budget changes at run-time, or perhaps you're changing levels in your game.) - void __cdecl GarbageCollect(); + SharedGraphicsResource(GraphicsResource&&); + SharedGraphicsResource&& operator= (GraphicsResource&&); - // Memory statistics - GraphicsMemoryStatistics __cdecl GetStatistics(); - void __cdecl ResetStatistics(); + SharedGraphicsResource(const SharedGraphicsResource&) noexcept; + SharedGraphicsResource& operator= (const SharedGraphicsResource&) noexcept; - // Singleton - // Should only use nullptr for single GPU scenarios; mGPU requires a specific device - static GraphicsMemory& __cdecl Get(_In_opt_ ID3D12Device* device = nullptr); + SharedGraphicsResource(const GraphicsResource&) = delete; + SharedGraphicsResource& operator= (const GraphicsResource&) = delete; - private: - // Private implementation. - class Impl; + ~SharedGraphicsResource(); - std::unique_ptr pImpl; - }; + D3D12_GPU_VIRTUAL_ADDRESS GpuAddress() const noexcept { return mSharedResource->GpuAddress(); } + ID3D12Resource* Resource() const noexcept { return mSharedResource->Resource(); } + void* Memory() const noexcept { return mSharedResource->Memory(); } + size_t ResourceOffset() const noexcept { return mSharedResource->ResourceOffset(); } + size_t Size() const noexcept { return mSharedResource->Size(); } + + explicit operator bool() const noexcept { return mSharedResource != nullptr; } + + bool operator == (const SharedGraphicsResource& other) const noexcept { return mSharedResource.get() == other.mSharedResource.get(); } + bool operator != (const SharedGraphicsResource& other) const noexcept { return mSharedResource.get() != other.mSharedResource.get(); } + + // Clear the pointer. Using operator -> will produce bad results. + void __cdecl Reset() noexcept; + void __cdecl Reset(GraphicsResource&&); + void __cdecl Reset(SharedGraphicsResource&&) noexcept; + void __cdecl Reset(const SharedGraphicsResource& resource) noexcept; + + private: + std::shared_ptr mSharedResource; + }; + + //------------------------------------------------------------------------------ + struct GraphicsMemoryStatistics + { + size_t committedMemory; // Bytes of memory currently committed/in-flight + size_t totalMemory; // Total bytes of memory used by the allocators + size_t totalPages; // Total page count + size_t peakCommitedMemory; // Peak commited memory value since last reset + size_t peakTotalMemory; // Peak total bytes + size_t peakTotalPages; // Peak total page count + }; + + //------------------------------------------------------------------------------ + class GraphicsMemory + { + public: + explicit GraphicsMemory(_In_ ID3D12Device* device); + + GraphicsMemory(GraphicsMemory&&) noexcept; + GraphicsMemory& operator= (GraphicsMemory&&) noexcept; + + GraphicsMemory(GraphicsMemory const&) = delete; + GraphicsMemory& operator=(GraphicsMemory const&) = delete; + + virtual ~GraphicsMemory(); + + // Make sure to keep the GraphicsResource handle alive as long as you need to access + // the memory on the CPU. For example, do not simply cache GpuAddress() and discard + // the GraphicsResource object, or your memory may be overwritten later. + GraphicsResource __cdecl Allocate(size_t size, size_t alignment = 16); + + // Special overload of Allocate that aligns to D3D12 constant buffer alignment requirements + template GraphicsResource AllocateConstant() + { + constexpr size_t alignment = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT; + constexpr size_t alignedSize = (sizeof(T) + alignment - 1) & ~(alignment - 1); + return Allocate(alignedSize, alignment); + } + template GraphicsResource AllocateConstant(const T& setData) + { + GraphicsResource alloc = AllocateConstant(); + memcpy(alloc.Memory(), &setData, sizeof(T)); + return alloc; + } + + // Submits all the pending one-shot memory to the GPU. + // The memory will be recycled once the GPU is done with it. + void __cdecl Commit(_In_ ID3D12CommandQueue* commandQueue); + + // This frees up any unused memory. + // If you want to make sure all memory is reclaimed, idle the GPU before calling this. + // It is not recommended that you call this unless absolutely necessary (e.g. your + // memory budget changes at run-time, or perhaps you're changing levels in your game.) + void __cdecl GarbageCollect(); + + // Memory statistics + GraphicsMemoryStatistics __cdecl GetStatistics(); + void __cdecl ResetStatistics(); + + // Singleton + // Should only use nullptr for single GPU scenarios; mGPU requires a specific device + static GraphicsMemory& __cdecl Get(_In_opt_ ID3D12Device* device = nullptr); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; + } } diff --git a/Kits/DirectXTK12/Inc/Model.h b/Kits/DirectXTK12/Inc/Model.h index 9e6fe35..7b140f6 100644 --- a/Kits/DirectXTK12/Inc/Model.h +++ b/Kits/DirectXTK12/Inc/Model.h @@ -48,148 +48,556 @@ namespace DirectX { - class IEffect; - class IEffectFactory; - class ModelMesh; - - //---------------------------------------------------------------------------------- - // Model loading options - enum ModelLoaderFlags : uint32_t + inline namespace DX12 { - ModelLoader_Default = 0x0, - ModelLoader_MaterialColorsSRGB = 0x1, - ModelLoader_AllowLargeModels = 0x2, - ModelLoader_IncludeBones = 0x4, - ModelLoader_DisableSkinning = 0x8, - }; + class IEffect; + class IEffectFactory; + class ModelMesh; - //---------------------------------------------------------------------------------- - // Frame hierarchy for rigid body and skeletal animation - struct ModelBone - { - ModelBone() noexcept : - parentIndex(c_Invalid), - childIndex(c_Invalid), - siblingIndex(c_Invalid) + //------------------------------------------------------------------------------ + // Model loading options + enum ModelLoaderFlags : uint32_t { - } + ModelLoader_Default = 0x0, + ModelLoader_MaterialColorsSRGB = 0x1, + ModelLoader_AllowLargeModels = 0x2, + ModelLoader_IncludeBones = 0x4, + ModelLoader_DisableSkinning = 0x8, + }; - ModelBone(uint32_t parent, uint32_t child, uint32_t sibling) noexcept : - parentIndex(parent), - childIndex(child), - siblingIndex(sibling) + //------------------------------------------------------------------------------ + // Frame hierarchy for rigid body and skeletal animation + struct ModelBone { - } - - uint32_t parentIndex; - uint32_t childIndex; - uint32_t siblingIndex; - std::wstring name; - - using Collection = std::vector; - - static constexpr uint32_t c_Invalid = uint32_t(-1); - - struct aligned_deleter { void operator()(void* p) noexcept { _aligned_free(p); } }; - - using TransformArray = std::unique_ptr; - - static TransformArray MakeArray(size_t count) - { - void* temp = _aligned_malloc(sizeof(XMMATRIX) * count, 16); - if (!temp) - throw std::bad_alloc(); - return TransformArray(static_cast(temp)); - } - }; - - //---------------------------------------------------------------------------------- - // Each mesh part is a submesh with a single effect - class ModelMeshPart - { - public: - ModelMeshPart(uint32_t partIndex) noexcept; - - ModelMeshPart(ModelMeshPart&&) = default; - ModelMeshPart& operator= (ModelMeshPart&&) = default; - - ModelMeshPart(ModelMeshPart const&) = default; - ModelMeshPart& operator= (ModelMeshPart const&) = default; - - virtual ~ModelMeshPart(); - - using Collection = std::vector>; - using DrawCallback = std::function; - using InputLayoutCollection = std::vector; - - uint32_t partIndex; // Unique index assigned per-part in a model. - uint32_t materialIndex; // Index of the material spec to use - uint32_t indexCount; - uint32_t startIndex; - int32_t vertexOffset; - uint32_t vertexStride; - uint32_t vertexCount; - uint32_t indexBufferSize; - uint32_t vertexBufferSize; - D3D_PRIMITIVE_TOPOLOGY primitiveType; - DXGI_FORMAT indexFormat; - SharedGraphicsResource indexBuffer; - SharedGraphicsResource vertexBuffer; - Microsoft::WRL::ComPtr staticIndexBuffer; - Microsoft::WRL::ComPtr staticVertexBuffer; - std::shared_ptr vbDecl; - - // Draw mesh part - void __cdecl Draw(_In_ ID3D12GraphicsCommandList* commandList) const; - - void __cdecl DrawInstanced(_In_ ID3D12GraphicsCommandList* commandList, uint32_t instanceCount, uint32_t startInstance = 0) const; - - // - // Utilities for drawing multiple mesh parts - // - - // Draw the mesh - static void __cdecl DrawMeshParts(_In_ ID3D12GraphicsCommandList* commandList, const Collection& meshParts); - - // Draw the mesh with an effect - static void __cdecl DrawMeshParts(_In_ ID3D12GraphicsCommandList* commandList, const Collection& meshParts, _In_ IEffect* effect); - - // Draw the mesh with a callback for each mesh part - static void __cdecl DrawMeshParts(_In_ ID3D12GraphicsCommandList* commandList, const Collection& meshParts, DrawCallback callback); - - // Draw the mesh with a range of effects that mesh parts will index into. - // Effects can be any IEffect pointer type (including smart pointer). Value or reference types will not compile. - // The iterator passed to this method should have random access capabilities for best performance. - template - static void DrawMeshParts( - _In_ ID3D12GraphicsCommandList* commandList, - const Collection& meshParts, - TEffectIterator partEffects) - { - // This assert is here to prevent accidental use of containers that would cause undesirable performance penalties. - static_assert( - std::is_base_of::value, - "Providing an iterator without random access capabilities -- such as from std::list -- is not supported."); - - for (const auto& it : meshParts) + ModelBone() noexcept : + parentIndex(c_Invalid), + childIndex(c_Invalid), + siblingIndex(c_Invalid) { - auto part = it.get(); - assert(part != nullptr); - - // Get the effect at the location specified by the part's material - TEffectIterator effect_iterator = partEffects; - std::advance(effect_iterator, part->partIndex); - - // Apply the effect and draw - (*effect_iterator)->Apply(commandList); - part->Draw(commandList); } - } - template - static void XM_CALLCONV DrawMeshParts( + ModelBone(uint32_t parent, uint32_t child, uint32_t sibling) noexcept : + parentIndex(parent), + childIndex(child), + siblingIndex(sibling) + { + } + + uint32_t parentIndex; + uint32_t childIndex; + uint32_t siblingIndex; + std::wstring name; + + using Collection = std::vector; + + static constexpr uint32_t c_Invalid = uint32_t(-1); + + struct aligned_deleter { void operator()(void* p) noexcept { _aligned_free(p); } }; + + using TransformArray = std::unique_ptr; + + static TransformArray MakeArray(size_t count) + { + void* temp = _aligned_malloc(sizeof(XMMATRIX) * count, 16); + if (!temp) + throw std::bad_alloc(); + return TransformArray(static_cast(temp)); + } + }; + + //------------------------------------------------------------------------------ + // Each mesh part is a submesh with a single effect + class ModelMeshPart + { + public: + ModelMeshPart(uint32_t partIndex) noexcept; + + ModelMeshPart(ModelMeshPart&&) = default; + ModelMeshPart& operator= (ModelMeshPart&&) = default; + + ModelMeshPart(ModelMeshPart const&) = default; + ModelMeshPart& operator= (ModelMeshPart const&) = default; + + virtual ~ModelMeshPart(); + + using Collection = std::vector>; + using DrawCallback = std::function; + using InputLayoutCollection = std::vector; + + uint32_t partIndex; // Unique index assigned per-part in a model. + uint32_t materialIndex; // Index of the material spec to use + uint32_t indexCount; + uint32_t startIndex; + int32_t vertexOffset; + uint32_t vertexStride; + uint32_t vertexCount; + uint32_t indexBufferSize; + uint32_t vertexBufferSize; + D3D_PRIMITIVE_TOPOLOGY primitiveType; + DXGI_FORMAT indexFormat; + SharedGraphicsResource indexBuffer; + SharedGraphicsResource vertexBuffer; + Microsoft::WRL::ComPtr staticIndexBuffer; + Microsoft::WRL::ComPtr staticVertexBuffer; + std::shared_ptr vbDecl; + + // Draw mesh part + void __cdecl Draw(_In_ ID3D12GraphicsCommandList* commandList) const; + + void __cdecl DrawInstanced(_In_ ID3D12GraphicsCommandList* commandList, uint32_t instanceCount, uint32_t startInstance = 0) const; + + // + // Utilities for drawing multiple mesh parts + // + + // Draw the mesh + static void __cdecl DrawMeshParts(_In_ ID3D12GraphicsCommandList* commandList, const Collection& meshParts); + + // Draw the mesh with an effect + static void __cdecl DrawMeshParts(_In_ ID3D12GraphicsCommandList* commandList, const Collection& meshParts, _In_ IEffect* effect); + + // Draw the mesh with a callback for each mesh part + static void __cdecl DrawMeshParts(_In_ ID3D12GraphicsCommandList* commandList, const Collection& meshParts, DrawCallback callback); + + // Draw the mesh with a range of effects that mesh parts will index into. + // Effects can be any IEffect pointer type (including smart pointer). Value or reference types will not compile. + // The iterator passed to this method should have random access capabilities for best performance. + template + static void DrawMeshParts( + _In_ ID3D12GraphicsCommandList* commandList, + const Collection& meshParts, + TEffectIterator partEffects) + { + // This assert is here to prevent accidental use of containers that would cause undesirable performance penalties. + static_assert( + std::is_base_of::value, + "Providing an iterator without random access capabilities -- such as from std::list -- is not supported."); + + for (const auto& it : meshParts) + { + auto part = it.get(); + assert(part != nullptr); + + // Get the effect at the location specified by the part's material + TEffectIterator effect_iterator = partEffects; + std::advance(effect_iterator, part->partIndex); + + // Apply the effect and draw + (*effect_iterator)->Apply(commandList); + part->Draw(commandList); + } + } + + template + static void XM_CALLCONV DrawMeshParts( + _In_ ID3D12GraphicsCommandList* commandList, + const Collection& meshParts, + FXMMATRIX world, + TEffectIterator partEffects) + { + // This assert is here to prevent accidental use of containers that would cause undesirable performance penalties. + static_assert( + std::is_base_of::value, + "Providing an iterator without random access capabilities -- such as from std::list -- is not supported."); + + for (const auto& it : meshParts) + { + auto part = it.get(); + assert(part != nullptr); + + // Get the effect at the location specified by the part's material + TEffectIterator effect_iterator = partEffects; + std::advance(effect_iterator, part->partIndex); + + auto imatrices = dynamic_cast((*effect_iterator).get()); + if (imatrices) + { + imatrices->SetWorld(world); + } + + // Apply the effect and draw + (*effect_iterator)->Apply(commandList); + part->Draw(commandList); + } + } + + template + static void XM_CALLCONV DrawSkinnedMeshParts( + _In_ ID3D12GraphicsCommandList* commandList, + const ModelMesh& mesh, + const Collection& meshParts, + size_t nbones, + _In_reads_(nbones) const XMMATRIX* boneTransforms, + FXMMATRIX world, + TEffectIterator partEffects); + }; + + + //------------------------------------------------------------------------------ + // A mesh consists of one or more model mesh parts + class ModelMesh + { + public: + ModelMesh() noexcept; + + ModelMesh(ModelMesh&&) = default; + ModelMesh& operator= (ModelMesh&&) = default; + + ModelMesh(ModelMesh const&) = default; + ModelMesh& operator= (ModelMesh const&) = default; + + virtual ~ModelMesh(); + + BoundingSphere boundingSphere; + BoundingBox boundingBox; + ModelMeshPart::Collection opaqueMeshParts; + ModelMeshPart::Collection alphaMeshParts; + uint32_t boneIndex; + std::vector boneInfluences; + std::wstring name; + + using Collection = std::vector>; + + // Draw the mesh + void __cdecl DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList) const; + void __cdecl DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList) const; + + // Draw the mesh with an effect + void __cdecl DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, _In_ IEffect* effect) const; + void __cdecl DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, _In_ IEffect* effect) const; + + // Draw the mesh with a callback for each mesh part + void __cdecl DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, ModelMeshPart::DrawCallback callback) const; + void __cdecl DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, ModelMeshPart::DrawCallback callback) const; + + // Draw the mesh with a range of effects that mesh parts will index into. + // TEffectPtr can be any IEffect pointer type (including smart pointer). Value or reference types will not compile. + template + void DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, TEffectIterator effects) const + { + ModelMeshPart::DrawMeshParts(commandList, opaqueMeshParts, effects); + } + template + void DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, TEffectIterator effects) const + { + ModelMeshPart::DrawMeshParts(commandList, alphaMeshParts, effects); + } + + // Draw rigid-body with bones. + template + void XM_CALLCONV DrawOpaque( + _In_ ID3D12GraphicsCommandList* commandList, + size_t nbones, + _In_reads_(nbones) const XMMATRIX* boneTransforms, + FXMMATRIX world, + TEffectIterator effects) const + { + assert(nbones > 0 && boneTransforms != nullptr); + XMMATRIX local; + if (boneIndex != ModelBone::c_Invalid && boneIndex < nbones) + { + local = XMMatrixMultiply(boneTransforms[boneIndex], world); + } + else + { + local = world; + } + + ModelMeshPart::DrawMeshParts(commandList, opaqueMeshParts, local, effects); + } + + template + void XM_CALLCONV DrawAlpha( + _In_ ID3D12GraphicsCommandList* commandList, + size_t nbones, + _In_reads_(nbones) const XMMATRIX* boneTransforms, + FXMMATRIX world, + TEffectIterator effects) const + { + assert(nbones > 0 && boneTransforms != nullptr); + XMMATRIX local; + if (boneIndex != ModelBone::c_Invalid && boneIndex < nbones) + { + local = XMMatrixMultiply(boneTransforms[boneIndex], world); + } + else + { + local = world; + } + + ModelMeshPart::DrawMeshParts(commandList, alphaMeshParts, local, effects); + } + + // Draw using skinning given bone transform array. + template + void XM_CALLCONV DrawSkinnedOpaque( + _In_ ID3D12GraphicsCommandList* commandList, + size_t nbones, + _In_reads_(nbones) const XMMATRIX* boneTransforms, + FXMMATRIX world, + TEffectIterator effects) const + { + ModelMeshPart::DrawSkinnedMeshParts(commandList, *this, opaqueMeshParts, + nbones, boneTransforms, world, effects); + } + + template + void XM_CALLCONV DrawSkinnedAlpha( + _In_ ID3D12GraphicsCommandList* commandList, + size_t nbones, + _In_reads_(nbones) const XMMATRIX* boneTransforms, + FXMMATRIX world, + TEffectIterator effects) const + { + ModelMeshPart::DrawSkinnedMeshParts(commandList, *this, alphaMeshParts, + nbones, boneTransforms, world, effects); + } + }; + + + //------------------------------------------------------------------------------ + // A model consists of one or more meshes + class Model + { + public: + Model() noexcept; + + Model(Model&&) = default; + Model& operator= (Model&&) = default; + + Model(Model const& other); + Model& operator= (Model const& rhs); + + virtual ~Model(); + + using EffectCollection = std::vector>; + using ModelMaterialInfo = IEffectFactory::EffectInfo; + using ModelMaterialInfoCollection = std::vector; + using TextureCollection = std::vector; + + // The Model::Draw* functions use variadic templates and perfect-forwarding in order to support future + // overloads to the ModelMesh::Draw* family of functions. This means that a new ModelMesh overload can be + // added, removed or altered, but the Model routines will still remain compatible. The correct ModelMesh + // overload will be selected by the compiler depending on the arguments you provide to the Model method. + + // Draw all the meshes in the model. + template void DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, TForwardArgs&&... args) const + { + // Draw opaque parts + for (const auto& it : meshes) + { + auto mesh = it.get(); + assert(mesh != nullptr); + + mesh->DrawOpaque(commandList, std::forward(args)...); + } + } + + template void DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, TForwardArgs&&... args) const + { + // Draw alpha parts + for (const auto& it : meshes) + { + auto mesh = it.get(); + assert(mesh != nullptr); + + mesh->DrawAlpha(commandList, std::forward(args)...); + } + } + + template void Draw(_In_ ID3D12GraphicsCommandList* commandList, TForwardArgs&&... args) const + { + DrawOpaque(commandList, args...); + DrawAlpha(commandList, std::forward(args)...); + } + + // Draw mesh using skinning given bone transform array. + template void DrawSkinnedOpaque(_In_ ID3D12GraphicsCommandList* commandList, TForwardArgs&&... args) const + { + // Draw opaque parts + for (const auto& it : meshes) + { + auto mesh = it.get(); + assert(mesh != nullptr); + + mesh->DrawSkinnedOpaque(commandList, std::forward(args)...); + } + } + + template void DrawSkinnedAlpha(_In_ ID3D12GraphicsCommandList* commandList, TForwardArgs&&... args) const + { + // Draw alpha parts + for (const auto& it : meshes) + { + auto mesh = it.get(); + assert(mesh != nullptr); + + mesh->DrawSkinnedAlpha(commandList, std::forward(args)...); + } + } + + template void DrawSkinned(_In_ ID3D12GraphicsCommandList* commandList, TForwardArgs&&... args) const + { + DrawSkinnedOpaque(commandList, args...); + DrawSkinnedAlpha(commandList, std::forward(args)...); + } + + // Load texture resources into an existing Effect Texture Factory + int __cdecl LoadTextures(IEffectTextureFactory& texFactory, int destinationDescriptorOffset = 0) const; + + // Load texture resources into a new Effect Texture Factory + std::unique_ptr __cdecl LoadTextures( + _In_ ID3D12Device* device, + ResourceUploadBatch& resourceUploadBatch, + _In_opt_z_ const wchar_t* texturesPath = nullptr, + D3D12_DESCRIPTOR_HEAP_FLAGS flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE) const; + + // Load VB/IB resources for static geometry + void __cdecl LoadStaticBuffers( + _In_ ID3D12Device* device, + ResourceUploadBatch& resourceUploadBatch, + bool keepMemory = false); + + // Create effects using the default effect factory + EffectCollection __cdecl CreateEffects( + const EffectPipelineStateDescription& opaquePipelineState, + const EffectPipelineStateDescription& alphaPipelineState, + _In_ ID3D12DescriptorHeap* textureDescriptorHeap, + _In_ ID3D12DescriptorHeap* samplerDescriptorHeap, + int textureDescriptorOffset = 0, + int samplerDescriptorOffset = 0) const; + + // Create effects using a custom effect factory + EffectCollection __cdecl CreateEffects( + IEffectFactory& fxFactory, + const EffectPipelineStateDescription& opaquePipelineState, + const EffectPipelineStateDescription& alphaPipelineState, + int textureDescriptorOffset = 0, + int samplerDescriptorOffset = 0) const; + + // Compute bone positions based on heirarchy and transform matrices + void __cdecl CopyAbsoluteBoneTransformsTo( + size_t nbones, + _Out_writes_(nbones) XMMATRIX* boneTransforms) const; + + void __cdecl CopyAbsoluteBoneTransforms( + size_t nbones, + _In_reads_(nbones) const XMMATRIX* inBoneTransforms, + _Out_writes_(nbones) XMMATRIX* outBoneTransforms) const; + + // Set bone matrices to a set of relative tansforms + void __cdecl CopyBoneTransformsFrom( + size_t nbones, + _In_reads_(nbones) const XMMATRIX* boneTransforms); + + // Copies the relative bone matrices to a transform array + void __cdecl CopyBoneTransformsTo( + size_t nbones, + _Out_writes_(nbones) XMMATRIX* boneTransforms) const; + + // Loads a model from a Visual Studio Starter Kit .CMO file + static std::unique_ptr __cdecl CreateFromCMO( + _In_opt_ ID3D12Device* device, + _In_reads_bytes_(dataSize) const uint8_t* meshData, _In_ size_t dataSize, + ModelLoaderFlags flags = ModelLoader_Default, + _Out_opt_ size_t* animsOffset = nullptr); + static std::unique_ptr __cdecl CreateFromCMO( + _In_opt_ ID3D12Device* device, + _In_z_ const wchar_t* szFileName, + ModelLoaderFlags flags = ModelLoader_Default, + _Out_opt_ size_t* animsOffset = nullptr); + + // Loads a model from a DirectX SDK .SDKMESH file + static std::unique_ptr __cdecl CreateFromSDKMESH( + _In_opt_ ID3D12Device* device, + _In_reads_bytes_(dataSize) const uint8_t* meshData, _In_ size_t dataSize, + ModelLoaderFlags flags = ModelLoader_Default); + static std::unique_ptr __cdecl CreateFromSDKMESH( + _In_opt_ ID3D12Device* device, + _In_z_ const wchar_t* szFileName, + ModelLoaderFlags flags = ModelLoader_Default); + + // Loads a model from a .VBO file + static std::unique_ptr __cdecl CreateFromVBO( + _In_opt_ ID3D12Device* device, + _In_reads_bytes_(dataSize) const uint8_t* meshData, _In_ size_t dataSize, + ModelLoaderFlags flags = ModelLoader_Default); + static std::unique_ptr __cdecl CreateFromVBO( + _In_opt_ ID3D12Device* device, + _In_z_ const wchar_t* szFileName, + ModelLoaderFlags flags = ModelLoader_Default); + + // Utility function for getting a GPU descriptor for a mesh part/material index. If there is no texture the + // descriptor will be zero. + D3D12_GPU_DESCRIPTOR_HANDLE __cdecl GetGpuTextureHandleForMaterialIndex(uint32_t materialIndex, _In_ ID3D12DescriptorHeap* heap, _In_ size_t descriptorSize, _In_ size_t descriptorOffset) const + { + D3D12_GPU_DESCRIPTOR_HANDLE handle = {}; + + if (materialIndex >= materials.size()) + return handle; + + const int textureIndex = materials[materialIndex].diffuseTextureIndex; + if (textureIndex == -1) + return handle; + + #if defined(_MSC_VER) || !defined(_WIN32) + handle = heap->GetGPUDescriptorHandleForHeapStart(); + #else + std::ignore = heap->GetGPUDescriptorHandleForHeapStart(&handle); + #endif + handle.ptr += static_cast(descriptorSize * (UINT64(textureIndex) + UINT64(descriptorOffset))); + + return handle; + } + + // Utility function for updating the matrices in a list of effects. This will SetWorld, SetView and SetProjection + // on any effect in the list that derives from IEffectMatrices. + static void XM_CALLCONV UpdateEffectMatrices( + EffectCollection& effects, + FXMMATRIX world, + CXMMATRIX view, + CXMMATRIX proj); + + // Utility function to transition VB/IB resources for static geometry. + void __cdecl Transition( + _In_ ID3D12GraphicsCommandList* commandList, + D3D12_RESOURCE_STATES stateBeforeVB, + D3D12_RESOURCE_STATES stateAfterVB, + D3D12_RESOURCE_STATES stateBeforeIB, + D3D12_RESOURCE_STATES stateAfterIB); + + ModelMesh::Collection meshes; + ModelMaterialInfoCollection materials; + TextureCollection textureNames; + ModelBone::Collection bones; + ModelBone::TransformArray boneMatrices; + ModelBone::TransformArray invBindPoseMatrices; + std::wstring name; + + private: + std::shared_ptr __cdecl CreateEffectForMeshPart( + IEffectFactory& fxFactory, + const EffectPipelineStateDescription& opaquePipelineState, + const EffectPipelineStateDescription& alphaPipelineState, + int textureDescriptorOffset, + int samplerDescriptorOffset, + _In_ const ModelMeshPart* part) const; + + void __cdecl ComputeAbsolute(uint32_t index, + CXMMATRIX local, size_t nbones, + _In_reads_(nbones) const XMMATRIX* inBoneTransforms, + _Inout_updates_(nbones) XMMATRIX* outBoneTransforms, + size_t& visited) const; + }; + + + template + void XM_CALLCONV ModelMeshPart::DrawSkinnedMeshParts( _In_ ID3D12GraphicsCommandList* commandList, - const Collection& meshParts, + const ModelMesh& mesh, + const ModelMeshPart::Collection& meshParts, + size_t nbones, + _In_reads_(nbones) const XMMATRIX* boneTransforms, FXMMATRIX world, TEffectIterator partEffects) { @@ -198,9 +606,13 @@ namespace DirectX std::is_base_of::value, "Providing an iterator without random access capabilities -- such as from std::list -- is not supported."); - for (const auto& it : meshParts) + assert(nbones > 0 && boneTransforms != nullptr); + + ModelBone::TransformArray temp; + + for (const auto& mit : meshParts) { - auto part = it.get(); + auto part = mit.get(); assert(part != nullptr); // Get the effect at the location specified by the part's material @@ -213,473 +625,68 @@ namespace DirectX imatrices->SetWorld(world); } + auto iskinning = dynamic_cast((*effect_iterator).get()); + if (iskinning) + { + if (mesh.boneInfluences.empty()) + { + // Direct-mapping of vertex bone indices to our master bone array + iskinning->SetBoneTransforms(boneTransforms, nbones); + } + else + { + if (!temp) + { + // Create the influence mapped bones on-demand. + temp = ModelBone::MakeArray(IEffectSkinning::MaxBones); + + size_t count = 0; + for (auto it : mesh.boneInfluences) + { + ++count; + if (count > IEffectSkinning::MaxBones) + { + throw std::runtime_error("Too many bones for skinning"); + } + + if (it >= nbones) + { + throw std::runtime_error("Invalid bone influence index"); + } + + temp[count - 1] = boneTransforms[it]; + } + + assert(count == mesh.boneInfluences.size()); + } + + iskinning->SetBoneTransforms(temp.get(), mesh.boneInfluences.size()); + } + } + else if (imatrices) + { + // Fallback for if we encounter a non-skinning effect in the model + XMMATRIX bm = (mesh.boneIndex != ModelBone::c_Invalid && mesh.boneIndex < nbones) + ? boneTransforms[mesh.boneIndex] : XMMatrixIdentity(); + + imatrices->SetWorld(XMMatrixMultiply(bm, world)); + } + // Apply the effect and draw (*effect_iterator)->Apply(commandList); part->Draw(commandList); } } - template - static void XM_CALLCONV DrawSkinnedMeshParts( - _In_ ID3D12GraphicsCommandList* commandList, - const ModelMesh& mesh, - const Collection& meshParts, - size_t nbones, - _In_reads_(nbones) const XMMATRIX* boneTransforms, - FXMMATRIX world, - TEffectIterator partEffects); - }; + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-dynamic-exception-spec" + #endif + DEFINE_ENUM_FLAG_OPERATORS(ModelLoaderFlags); - //---------------------------------------------------------------------------------- - // A mesh consists of one or more model mesh parts - class ModelMesh - { - public: - ModelMesh() noexcept; - - ModelMesh(ModelMesh&&) = default; - ModelMesh& operator= (ModelMesh&&) = default; - - ModelMesh(ModelMesh const&) = default; - ModelMesh& operator= (ModelMesh const&) = default; - - virtual ~ModelMesh(); - - BoundingSphere boundingSphere; - BoundingBox boundingBox; - ModelMeshPart::Collection opaqueMeshParts; - ModelMeshPart::Collection alphaMeshParts; - uint32_t boneIndex; - std::vector boneInfluences; - std::wstring name; - - using Collection = std::vector>; - - // Draw the mesh - void __cdecl DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList) const; - void __cdecl DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList) const; - - // Draw the mesh with an effect - void __cdecl DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, _In_ IEffect* effect) const; - void __cdecl DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, _In_ IEffect* effect) const; - - // Draw the mesh with a callback for each mesh part - void __cdecl DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, ModelMeshPart::DrawCallback callback) const; - void __cdecl DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, ModelMeshPart::DrawCallback callback) const; - - // Draw the mesh with a range of effects that mesh parts will index into. - // TEffectPtr can be any IEffect pointer type (including smart pointer). Value or reference types will not compile. - template - void DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, TEffectIterator effects) const - { - ModelMeshPart::DrawMeshParts(commandList, opaqueMeshParts, effects); - } - template - void DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, TEffectIterator effects) const - { - ModelMeshPart::DrawMeshParts(commandList, alphaMeshParts, effects); - } - - // Draw rigid-body with bones. - template - void XM_CALLCONV DrawOpaque( - _In_ ID3D12GraphicsCommandList* commandList, - size_t nbones, - _In_reads_(nbones) const XMMATRIX* boneTransforms, - FXMMATRIX world, - TEffectIterator effects) const - { - assert(nbones > 0 && boneTransforms != nullptr); - XMMATRIX local; - if (boneIndex != ModelBone::c_Invalid && boneIndex < nbones) - { - local = XMMatrixMultiply(boneTransforms[boneIndex], world); - } - else - { - local = world; - } - - ModelMeshPart::DrawMeshParts(commandList, opaqueMeshParts, local, effects); - } - - template - void XM_CALLCONV DrawAlpha( - _In_ ID3D12GraphicsCommandList* commandList, - size_t nbones, - _In_reads_(nbones) const XMMATRIX* boneTransforms, - FXMMATRIX world, - TEffectIterator effects) const - { - assert(nbones > 0 && boneTransforms != nullptr); - XMMATRIX local; - if (boneIndex != ModelBone::c_Invalid && boneIndex < nbones) - { - local = XMMatrixMultiply(boneTransforms[boneIndex], world); - } - else - { - local = world; - } - - ModelMeshPart::DrawMeshParts(commandList, alphaMeshParts, local, effects); - } - - // Draw using skinning given bone transform array. - template - void XM_CALLCONV DrawSkinnedOpaque( - _In_ ID3D12GraphicsCommandList* commandList, - size_t nbones, - _In_reads_(nbones) const XMMATRIX* boneTransforms, - FXMMATRIX world, - TEffectIterator effects) const - { - ModelMeshPart::DrawSkinnedMeshParts(commandList, *this, opaqueMeshParts, - nbones, boneTransforms, world, effects); - } - - template - void XM_CALLCONV DrawSkinnedAlpha( - _In_ ID3D12GraphicsCommandList* commandList, - size_t nbones, - _In_reads_(nbones) const XMMATRIX* boneTransforms, - FXMMATRIX world, - TEffectIterator effects) const - { - ModelMeshPart::DrawSkinnedMeshParts(commandList, *this, alphaMeshParts, - nbones, boneTransforms, world, effects); - } - }; - - - //---------------------------------------------------------------------------------- - // A model consists of one or more meshes - class Model - { - public: - Model() noexcept; - - Model(Model&&) = default; - Model& operator= (Model&&) = default; - - Model(Model const& other); - Model& operator= (Model const& rhs); - - virtual ~Model(); - - using EffectCollection = std::vector>; - using ModelMaterialInfo = IEffectFactory::EffectInfo; - using ModelMaterialInfoCollection = std::vector; - using TextureCollection = std::vector; - - // The Model::Draw* functions use variadic templates and perfect-forwarding in order to support future - // overloads to the ModelMesh::Draw* family of functions. This means that a new ModelMesh overload can be - // added, removed or altered, but the Model routines will still remain compatible. The correct ModelMesh - // overload will be selected by the compiler depending on the arguments you provide to the Model method. - - // Draw all the meshes in the model. - template void DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, TForwardArgs&&... args) const - { - // Draw opaque parts - for (const auto& it : meshes) - { - auto mesh = it.get(); - assert(mesh != nullptr); - - mesh->DrawOpaque(commandList, std::forward(args)...); - } - } - - template void DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, TForwardArgs&&... args) const - { - // Draw alpha parts - for (const auto& it : meshes) - { - auto mesh = it.get(); - assert(mesh != nullptr); - - mesh->DrawAlpha(commandList, std::forward(args)...); - } - } - - template void Draw(_In_ ID3D12GraphicsCommandList* commandList, TForwardArgs&&... args) const - { - DrawOpaque(commandList, args...); - DrawAlpha(commandList, std::forward(args)...); - } - - // Draw mesh using skinning given bone transform array. - template void DrawSkinnedOpaque(_In_ ID3D12GraphicsCommandList* commandList, TForwardArgs&&... args) const - { - // Draw opaque parts - for (const auto& it : meshes) - { - auto mesh = it.get(); - assert(mesh != nullptr); - - mesh->DrawSkinnedOpaque(commandList, std::forward(args)...); - } - } - - template void DrawSkinnedAlpha(_In_ ID3D12GraphicsCommandList* commandList, TForwardArgs&&... args) const - { - // Draw alpha parts - for (const auto& it : meshes) - { - auto mesh = it.get(); - assert(mesh != nullptr); - - mesh->DrawSkinnedAlpha(commandList, std::forward(args)...); - } - } - - template void DrawSkinned(_In_ ID3D12GraphicsCommandList* commandList, TForwardArgs&&... args) const - { - DrawSkinnedOpaque(commandList, args...); - DrawSkinnedAlpha(commandList, std::forward(args)...); - } - - // Load texture resources into an existing Effect Texture Factory - int __cdecl LoadTextures(IEffectTextureFactory& texFactory, int destinationDescriptorOffset = 0) const; - - // Load texture resources into a new Effect Texture Factory - std::unique_ptr __cdecl LoadTextures( - _In_ ID3D12Device* device, - ResourceUploadBatch& resourceUploadBatch, - _In_opt_z_ const wchar_t* texturesPath = nullptr, - D3D12_DESCRIPTOR_HEAP_FLAGS flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE) const; - - // Load VB/IB resources for static geometry - void __cdecl LoadStaticBuffers( - _In_ ID3D12Device* device, - ResourceUploadBatch& resourceUploadBatch, - bool keepMemory = false); - - // Create effects using the default effect factory - EffectCollection __cdecl CreateEffects( - const EffectPipelineStateDescription& opaquePipelineState, - const EffectPipelineStateDescription& alphaPipelineState, - _In_ ID3D12DescriptorHeap* textureDescriptorHeap, - _In_ ID3D12DescriptorHeap* samplerDescriptorHeap, - int textureDescriptorOffset = 0, - int samplerDescriptorOffset = 0) const; - - // Create effects using a custom effect factory - EffectCollection __cdecl CreateEffects( - IEffectFactory& fxFactory, - const EffectPipelineStateDescription& opaquePipelineState, - const EffectPipelineStateDescription& alphaPipelineState, - int textureDescriptorOffset = 0, - int samplerDescriptorOffset = 0) const; - - // Compute bone positions based on heirarchy and transform matrices - void __cdecl CopyAbsoluteBoneTransformsTo( - size_t nbones, - _Out_writes_(nbones) XMMATRIX* boneTransforms) const; - - void __cdecl CopyAbsoluteBoneTransforms( - size_t nbones, - _In_reads_(nbones) const XMMATRIX* inBoneTransforms, - _Out_writes_(nbones) XMMATRIX* outBoneTransforms) const; - - // Set bone matrices to a set of relative tansforms - void __cdecl CopyBoneTransformsFrom( - size_t nbones, - _In_reads_(nbones) const XMMATRIX* boneTransforms); - - // Copies the relative bone matrices to a transform array - void __cdecl CopyBoneTransformsTo( - size_t nbones, - _Out_writes_(nbones) XMMATRIX* boneTransforms) const; - - // Loads a model from a Visual Studio Starter Kit .CMO file - static std::unique_ptr __cdecl CreateFromCMO( - _In_opt_ ID3D12Device* device, - _In_reads_bytes_(dataSize) const uint8_t* meshData, _In_ size_t dataSize, - ModelLoaderFlags flags = ModelLoader_Default, - _Out_opt_ size_t* animsOffset = nullptr); - static std::unique_ptr __cdecl CreateFromCMO( - _In_opt_ ID3D12Device* device, - _In_z_ const wchar_t* szFileName, - ModelLoaderFlags flags = ModelLoader_Default, - _Out_opt_ size_t* animsOffset = nullptr); - - // Loads a model from a DirectX SDK .SDKMESH file - static std::unique_ptr __cdecl CreateFromSDKMESH( - _In_opt_ ID3D12Device* device, - _In_reads_bytes_(dataSize) const uint8_t* meshData, _In_ size_t dataSize, - ModelLoaderFlags flags = ModelLoader_Default); - static std::unique_ptr __cdecl CreateFromSDKMESH( - _In_opt_ ID3D12Device* device, - _In_z_ const wchar_t* szFileName, - ModelLoaderFlags flags = ModelLoader_Default); - - // Loads a model from a .VBO file - static std::unique_ptr __cdecl CreateFromVBO( - _In_opt_ ID3D12Device* device, - _In_reads_bytes_(dataSize) const uint8_t* meshData, _In_ size_t dataSize, - ModelLoaderFlags flags = ModelLoader_Default); - static std::unique_ptr __cdecl CreateFromVBO( - _In_opt_ ID3D12Device* device, - _In_z_ const wchar_t* szFileName, - ModelLoaderFlags flags = ModelLoader_Default); - - // Utility function for getting a GPU descriptor for a mesh part/material index. If there is no texture the - // descriptor will be zero. - D3D12_GPU_DESCRIPTOR_HANDLE __cdecl GetGpuTextureHandleForMaterialIndex(uint32_t materialIndex, _In_ ID3D12DescriptorHeap* heap, _In_ size_t descriptorSize, _In_ size_t descriptorOffset) const - { - D3D12_GPU_DESCRIPTOR_HANDLE handle = {}; - - if (materialIndex >= materials.size()) - return handle; - - const int textureIndex = materials[materialIndex].diffuseTextureIndex; - if (textureIndex == -1) - return handle; - - handle = heap->GetGPUDescriptorHandleForHeapStart(); - handle.ptr += static_cast(descriptorSize * (UINT64(textureIndex) + UINT64(descriptorOffset))); - - return handle; - } - - // Utility function for updating the matrices in a list of effects. This will SetWorld, SetView and SetProjection - // on any effect in the list that derives from IEffectMatrices. - static void XM_CALLCONV UpdateEffectMatrices( - EffectCollection& effects, - FXMMATRIX world, - CXMMATRIX view, - CXMMATRIX proj); - - // Utility function to transition VB/IB resources for static geometry. - void __cdecl Transition( - _In_ ID3D12GraphicsCommandList* commandList, - D3D12_RESOURCE_STATES stateBeforeVB, - D3D12_RESOURCE_STATES stateAfterVB, - D3D12_RESOURCE_STATES stateBeforeIB, - D3D12_RESOURCE_STATES stateAfterIB); - - ModelMesh::Collection meshes; - ModelMaterialInfoCollection materials; - TextureCollection textureNames; - ModelBone::Collection bones; - ModelBone::TransformArray boneMatrices; - ModelBone::TransformArray invBindPoseMatrices; - std::wstring name; - - private: - std::shared_ptr __cdecl CreateEffectForMeshPart( - IEffectFactory& fxFactory, - const EffectPipelineStateDescription& opaquePipelineState, - const EffectPipelineStateDescription& alphaPipelineState, - int textureDescriptorOffset, - int samplerDescriptorOffset, - _In_ const ModelMeshPart* part) const; - - void __cdecl ComputeAbsolute(uint32_t index, - CXMMATRIX local, size_t nbones, - _In_reads_(nbones) const XMMATRIX* inBoneTransforms, - _Inout_updates_(nbones) XMMATRIX* outBoneTransforms, - size_t& visited) const; - }; - - - template - void XM_CALLCONV ModelMeshPart::DrawSkinnedMeshParts( - _In_ ID3D12GraphicsCommandList* commandList, - const ModelMesh& mesh, - const ModelMeshPart::Collection& meshParts, - size_t nbones, - _In_reads_(nbones) const XMMATRIX* boneTransforms, - FXMMATRIX world, - TEffectIterator partEffects) - { - // This assert is here to prevent accidental use of containers that would cause undesirable performance penalties. - static_assert( - std::is_base_of::value, - "Providing an iterator without random access capabilities -- such as from std::list -- is not supported."); - - assert(nbones > 0 && boneTransforms != nullptr); - - ModelBone::TransformArray temp; - - for (const auto& mit : meshParts) - { - auto part = mit.get(); - assert(part != nullptr); - - // Get the effect at the location specified by the part's material - TEffectIterator effect_iterator = partEffects; - std::advance(effect_iterator, part->partIndex); - - auto imatrices = dynamic_cast((*effect_iterator).get()); - if (imatrices) - { - imatrices->SetWorld(world); - } - - auto iskinning = dynamic_cast((*effect_iterator).get()); - if (iskinning) - { - if (mesh.boneInfluences.empty()) - { - // Direct-mapping of vertex bone indices to our master bone array - iskinning->SetBoneTransforms(boneTransforms, nbones); - } - else - { - if (!temp) - { - // Create the influence mapped bones on-demand. - temp = ModelBone::MakeArray(IEffectSkinning::MaxBones); - - size_t count = 0; - for (auto it : mesh.boneInfluences) - { - ++count; - if (count > IEffectSkinning::MaxBones) - { - throw std::runtime_error("Too many bones for skinning"); - } - - if (it >= nbones) - { - throw std::runtime_error("Invalid bone influence index"); - } - - temp[count - 1] = boneTransforms[it]; - } - - assert(count == mesh.boneInfluences.size()); - } - - iskinning->SetBoneTransforms(temp.get(), mesh.boneInfluences.size()); - } - } - else if (imatrices) - { - // Fallback for if we encounter a non-skinning effect in the model - XMMATRIX bm = (mesh.boneIndex != ModelBone::c_Invalid && mesh.boneIndex < nbones) - ? boneTransforms[mesh.boneIndex] : XMMatrixIdentity(); - - imatrices->SetWorld(XMMatrixMultiply(bm, world)); - } - - // Apply the effect and draw - (*effect_iterator)->Apply(commandList); - part->Draw(commandList); - } + #ifdef __clang__ + #pragma clang diagnostic pop + #endif } - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-dynamic-exception-spec" -#endif - - DEFINE_ENUM_FLAG_OPERATORS(ModelLoaderFlags); - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif } diff --git a/Kits/DirectXTK12/Inc/PostProcess.h b/Kits/DirectXTK12/Inc/PostProcess.h index 028257e..ed71b42 100644 --- a/Kits/DirectXTK12/Inc/PostProcess.h +++ b/Kits/DirectXTK12/Inc/PostProcess.h @@ -29,186 +29,189 @@ namespace DirectX { - //---------------------------------------------------------------------------------- - // Abstract interface representing a post-process pass - class IPostProcess + inline namespace DX12 { - public: - virtual ~IPostProcess() = default; - - IPostProcess(const IPostProcess&) = delete; - IPostProcess& operator=(const IPostProcess&) = delete; - - virtual void __cdecl Process(_In_ ID3D12GraphicsCommandList* commandList) = 0; - - protected: - IPostProcess() = default; - IPostProcess(IPostProcess&&) = default; - IPostProcess& operator=(IPostProcess&&) = default; - }; - - - //---------------------------------------------------------------------------------- - // Basic post-process - class BasicPostProcess : public IPostProcess - { - public: - enum Effect : unsigned int + //------------------------------------------------------------------------------ + // Abstract interface representing a post-process pass + class IPostProcess { - Copy, - Monochrome, - Sepia, - DownScale_2x2, - DownScale_4x4, - GaussianBlur_5x5, - BloomExtract, - BloomBlur, - Effect_Max + public: + virtual ~IPostProcess() = default; + + IPostProcess(const IPostProcess&) = delete; + IPostProcess& operator=(const IPostProcess&) = delete; + + virtual void __cdecl Process(_In_ ID3D12GraphicsCommandList* commandList) = 0; + + protected: + IPostProcess() = default; + IPostProcess(IPostProcess&&) = default; + IPostProcess& operator=(IPostProcess&&) = default; }; - BasicPostProcess(_In_ ID3D12Device* device, const RenderTargetState& rtState, Effect fx); - BasicPostProcess(BasicPostProcess&&) noexcept; - BasicPostProcess& operator= (BasicPostProcess&&) noexcept; - - BasicPostProcess(BasicPostProcess const&) = delete; - BasicPostProcess& operator= (BasicPostProcess const&) = delete; - - ~BasicPostProcess() override; - - // IPostProcess methods. - void __cdecl Process(_In_ ID3D12GraphicsCommandList* commandList) override; - - // Properties - void __cdecl SetSourceTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, _In_opt_ ID3D12Resource* resource); - - // Sets multiplier for GaussianBlur_5x5 - void __cdecl SetGaussianParameter(float multiplier); - - // Sets parameters for BloomExtract - void __cdecl SetBloomExtractParameter(float threshold); - - // Sets parameters for BloomBlur - void __cdecl SetBloomBlurParameters(bool horizontal, float size, float brightness); - - private: - // Private implementation. - class Impl; - - std::unique_ptr pImpl; - }; - - - //---------------------------------------------------------------------------------- - // Dual-texure post-process - class DualPostProcess : public IPostProcess - { - public: - enum Effect : unsigned int + //------------------------------------------------------------------------------ + // Basic post-process + class BasicPostProcess : public IPostProcess { - Merge, - BloomCombine, - Effect_Max + public: + enum Effect : unsigned int + { + Copy, + Monochrome, + Sepia, + DownScale_2x2, + DownScale_4x4, + GaussianBlur_5x5, + BloomExtract, + BloomBlur, + Effect_Max + }; + + BasicPostProcess(_In_ ID3D12Device* device, const RenderTargetState& rtState, Effect fx); + + BasicPostProcess(BasicPostProcess&&) noexcept; + BasicPostProcess& operator= (BasicPostProcess&&) noexcept; + + BasicPostProcess(BasicPostProcess const&) = delete; + BasicPostProcess& operator= (BasicPostProcess const&) = delete; + + ~BasicPostProcess() override; + + // IPostProcess methods. + void __cdecl Process(_In_ ID3D12GraphicsCommandList* commandList) override; + + // Properties + void __cdecl SetSourceTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, _In_opt_ ID3D12Resource* resource); + + // Sets multiplier for GaussianBlur_5x5 + void __cdecl SetGaussianParameter(float multiplier); + + // Sets parameters for BloomExtract + void __cdecl SetBloomExtractParameter(float threshold); + + // Sets parameters for BloomBlur + void __cdecl SetBloomBlurParameters(bool horizontal, float size, float brightness); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; }; - DualPostProcess(_In_ ID3D12Device* device, const RenderTargetState& rtState, Effect fx); - DualPostProcess(DualPostProcess&&) noexcept; - DualPostProcess& operator= (DualPostProcess&&) noexcept; - - DualPostProcess(DualPostProcess const&) = delete; - DualPostProcess& operator= (DualPostProcess const&) = delete; - - ~DualPostProcess() override; - - // IPostProcess methods. - void __cdecl Process(_In_ ID3D12GraphicsCommandList* commandList) override; - - // Properties - void __cdecl SetSourceTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); - void __cdecl SetSourceTexture2(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); - - // Sets parameters for Merge - void __cdecl SetMergeParameters(float weight1, float weight2); - - // Sets parameters for BloomCombine - void __cdecl SetBloomCombineParameters(float bloom, float base, float bloomSaturation, float baseSaturation); - - private: - // Private implementation. - class Impl; - - std::unique_ptr pImpl; - }; - - - //---------------------------------------------------------------------------------- - // Tone-map post-process - class ToneMapPostProcess : public IPostProcess - { - public: - // Tone-mapping operator - enum Operator : unsigned int + //------------------------------------------------------------------------------ + // Dual-texure post-process + class DualPostProcess : public IPostProcess { - None, // Pass-through - Saturate, // Clamp [0,1] - Reinhard, // x/(1+x) - ACESFilmic, - Operator_Max + public: + enum Effect : unsigned int + { + Merge, + BloomCombine, + Effect_Max + }; + + DualPostProcess(_In_ ID3D12Device* device, const RenderTargetState& rtState, Effect fx); + + DualPostProcess(DualPostProcess&&) noexcept; + DualPostProcess& operator= (DualPostProcess&&) noexcept; + + DualPostProcess(DualPostProcess const&) = delete; + DualPostProcess& operator= (DualPostProcess const&) = delete; + + ~DualPostProcess() override; + + // IPostProcess methods. + void __cdecl Process(_In_ ID3D12GraphicsCommandList* commandList) override; + + // Properties + void __cdecl SetSourceTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); + void __cdecl SetSourceTexture2(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); + + // Sets parameters for Merge + void __cdecl SetMergeParameters(float weight1, float weight2); + + // Sets parameters for BloomCombine + void __cdecl SetBloomCombineParameters(float bloom, float base, float bloomSaturation, float baseSaturation); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; }; - // Electro-Optical Transfer Function (EOTF) - enum TransferFunction : unsigned int + + //------------------------------------------------------------------------------ + // Tone-map post-process + class ToneMapPostProcess : public IPostProcess { - Linear, // Pass-through - SRGB, // sRGB (Rec.709 and approximate sRGB display curve) - ST2084, // HDR10 (Rec.2020 color primaries and ST.2084 display curve) - TransferFunction_Max + public: + // Tone-mapping operator + enum Operator : unsigned int + { + None, // Pass-through + Saturate, // Clamp [0,1] + Reinhard, // x/(1+x) + ACESFilmic, + Operator_Max + }; + + // Electro-Optical Transfer Function (EOTF) + enum TransferFunction : unsigned int + { + Linear, // Pass-through + SRGB, // sRGB (Rec.709 and approximate sRGB display curve) + ST2084, // HDR10 (Rec.2020 color primaries and ST.2084 display curve) + TransferFunction_Max + }; + + // Color Rotation Transform for HDR10 + enum ColorPrimaryRotation : unsigned int + { + HDTV_to_UHDTV, // Rec.709 to Rec.2020 + DCI_P3_D65_to_UHDTV, // DCI-P3-D65 (a.k.a Display P3 or P3D65) to Rec.2020 + HDTV_to_DCI_P3_D65, // Rec.709 to DCI-P3-D65 (a.k.a Display P3 or P3D65) + }; + + ToneMapPostProcess(_In_ ID3D12Device* device, const RenderTargetState& rtState, + Operator op, TransferFunction func + #if (defined(_XBOX_ONE) && defined(_TITLE)) || defined(_GAMING_XBOX) + , bool mrt = false + #endif + ); + + ToneMapPostProcess(ToneMapPostProcess&&) noexcept; + ToneMapPostProcess& operator= (ToneMapPostProcess&&) noexcept; + + ToneMapPostProcess(ToneMapPostProcess const&) = delete; + ToneMapPostProcess& operator= (ToneMapPostProcess const&) = delete; + + ~ToneMapPostProcess() override; + + // IPostProcess methods. + void __cdecl Process(_In_ ID3D12GraphicsCommandList* commandList) override; + + // Properties + void __cdecl SetHDRSourceTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); + + // Sets the Color Rotation Transform for HDR10 signal output + void __cdecl SetColorRotation(ColorPrimaryRotation value); + void __cdecl SetColorRotation(CXMMATRIX value); + + // Sets exposure value for LDR tonemap operators + void __cdecl SetExposure(float exposureValue); + + // Sets ST.2084 parameter for how bright white should be in nits + void __cdecl SetST2084Parameter(float paperWhiteNits); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; }; - - // Color Rotation Transform for HDR10 - enum ColorPrimaryRotation : unsigned int - { - HDTV_to_UHDTV, // Rec.709 to Rec.2020 - DCI_P3_D65_to_UHDTV, // DCI-P3-D65 (a.k.a Display P3 or P3D65) to Rec.2020 - HDTV_to_DCI_P3_D65, // Rec.709 to DCI-P3-D65 (a.k.a Display P3 or P3D65) - }; - - ToneMapPostProcess(_In_ ID3D12Device* device, const RenderTargetState& rtState, - Operator op, TransferFunction func - #if (defined(_XBOX_ONE) && defined(_TITLE)) || defined(_GAMING_XBOX) - , bool mrt = false - #endif - ); - - ToneMapPostProcess(ToneMapPostProcess&&) noexcept; - ToneMapPostProcess& operator= (ToneMapPostProcess&&) noexcept; - - ToneMapPostProcess(ToneMapPostProcess const&) = delete; - ToneMapPostProcess& operator= (ToneMapPostProcess const&) = delete; - - ~ToneMapPostProcess() override; - - // IPostProcess methods. - void __cdecl Process(_In_ ID3D12GraphicsCommandList* commandList) override; - - // Properties - void __cdecl SetHDRSourceTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); - - // Sets the Color Rotation Transform for HDR10 signal output - void __cdecl SetColorRotation(ColorPrimaryRotation value); - void __cdecl SetColorRotation(CXMMATRIX value); - - // Sets exposure value for LDR tonemap operators - void __cdecl SetExposure(float exposureValue); - - // Sets ST.2084 parameter for how bright white should be in nits - void __cdecl SetST2084Parameter(float paperWhiteNits); - - private: - // Private implementation. - class Impl; - - std::unique_ptr pImpl; - }; + } } diff --git a/Kits/DirectXTK12/Inc/PrimitiveBatch.h b/Kits/DirectXTK12/Inc/PrimitiveBatch.h index be66886..2d0aaff 100644 --- a/Kits/DirectXTK12/Inc/PrimitiveBatch.h +++ b/Kits/DirectXTK12/Inc/PrimitiveBatch.h @@ -29,117 +29,119 @@ namespace DirectX { - namespace Internal + inline namespace DX12 { - // Base class, not to be used directly: clients should access this via the derived PrimitiveBatch. - class PrimitiveBatchBase + namespace Private { - protected: - PrimitiveBatchBase(_In_ ID3D12Device* device, size_t maxIndices, size_t maxVertices, size_t vertexSize); + // Base class, not to be used directly: clients should access this via the derived PrimitiveBatch. + class PrimitiveBatchBase + { + protected: + PrimitiveBatchBase(_In_ ID3D12Device* device, size_t maxIndices, size_t maxVertices, size_t vertexSize); - PrimitiveBatchBase(PrimitiveBatchBase&&) noexcept; - PrimitiveBatchBase& operator= (PrimitiveBatchBase&&) noexcept; + PrimitiveBatchBase(PrimitiveBatchBase&&) noexcept; + PrimitiveBatchBase& operator= (PrimitiveBatchBase&&) noexcept; - PrimitiveBatchBase(PrimitiveBatchBase const&) = delete; - PrimitiveBatchBase& operator= (PrimitiveBatchBase const&) = delete; + PrimitiveBatchBase(PrimitiveBatchBase const&) = delete; + PrimitiveBatchBase& operator= (PrimitiveBatchBase const&) = delete; - virtual ~PrimitiveBatchBase(); + virtual ~PrimitiveBatchBase(); + + public: + // Begin/End a batch of primitive drawing operations. + void __cdecl Begin(_In_ ID3D12GraphicsCommandList* cmdList); + void __cdecl End(); + + protected: + // Internal, untyped drawing method. + void __cdecl Draw(D3D_PRIMITIVE_TOPOLOGY topology, bool isIndexed, _In_opt_count_(indexCount) uint16_t const* indices, size_t indexCount, size_t vertexCount, _Outptr_ void** pMappedVertices); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; + } + + // Template makes the API typesafe, eg. PrimitiveBatch. + template + class PrimitiveBatch : public Private::PrimitiveBatchBase + { + static constexpr size_t DefaultBatchSize = 4096; public: - // Begin/End a batch of primitive drawing operations. - void __cdecl Begin(_In_ ID3D12GraphicsCommandList* cmdList); - void __cdecl End(); + explicit PrimitiveBatch(_In_ ID3D12Device* device, + size_t maxIndices = DefaultBatchSize * 3, + size_t maxVertices = DefaultBatchSize) + : PrimitiveBatchBase(device, maxIndices, maxVertices, sizeof(TVertex)) + { + } - protected: - // Internal, untyped drawing method. - void __cdecl Draw(D3D_PRIMITIVE_TOPOLOGY topology, bool isIndexed, _In_opt_count_(indexCount) uint16_t const* indices, size_t indexCount, size_t vertexCount, _Outptr_ void** pMappedVertices); + PrimitiveBatch(PrimitiveBatch&&) = default; + PrimitiveBatch& operator= (PrimitiveBatch&&) = default; - private: - // Private implementation. - class Impl; + PrimitiveBatch(PrimitiveBatch const&) = delete; + PrimitiveBatch& operator= (PrimitiveBatch const&) = delete; - std::unique_ptr pImpl; + // Similar to the D3D9 API DrawPrimitiveUP. + void Draw(D3D_PRIMITIVE_TOPOLOGY topology, _In_reads_(vertexCount) TVertex const* vertices, size_t vertexCount) + { + void* mappedVertices; + + PrimitiveBatchBase::Draw(topology, false, nullptr, 0, vertexCount, &mappedVertices); + + memcpy(mappedVertices, vertices, vertexCount * sizeof(TVertex)); + } + + + // Similar to the D3D9 API DrawIndexedPrimitiveUP. + void DrawIndexed(D3D_PRIMITIVE_TOPOLOGY topology, _In_reads_(indexCount) uint16_t const* indices, size_t indexCount, _In_reads_(vertexCount) TVertex const* vertices, size_t vertexCount) + { + void* mappedVertices; + + PrimitiveBatchBase::Draw(topology, true, indices, indexCount, vertexCount, &mappedVertices); + + memcpy(mappedVertices, vertices, vertexCount * sizeof(TVertex)); + } + + + void DrawLine(TVertex const& v1, TVertex const& v2) + { + TVertex* mappedVertices; + + PrimitiveBatchBase::Draw(D3D_PRIMITIVE_TOPOLOGY_LINELIST, false, nullptr, 0, 2, reinterpret_cast(&mappedVertices)); + + mappedVertices[0] = v1; + mappedVertices[1] = v2; + } + + + void DrawTriangle(TVertex const& v1, TVertex const& v2, TVertex const& v3) + { + TVertex* mappedVertices; + + PrimitiveBatchBase::Draw(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, false, nullptr, 0, 3, reinterpret_cast(&mappedVertices)); + + mappedVertices[0] = v1; + mappedVertices[1] = v2; + mappedVertices[2] = v3; + } + + + void DrawQuad(TVertex const& v1, TVertex const& v2, TVertex const& v3, TVertex const& v4) + { + static const uint16_t quadIndices[] = { 0, 1, 2, 0, 2, 3 }; + + TVertex* mappedVertices; + + PrimitiveBatchBase::Draw(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, true, quadIndices, 6, 4, reinterpret_cast(&mappedVertices)); + + mappedVertices[0] = v1; + mappedVertices[1] = v2; + mappedVertices[2] = v3; + mappedVertices[3] = v4; + } }; } - - - // Template makes the API typesafe, eg. PrimitiveBatch. - template - class PrimitiveBatch : public Internal::PrimitiveBatchBase - { - static constexpr size_t DefaultBatchSize = 4096; - - public: - explicit PrimitiveBatch(_In_ ID3D12Device* device, - size_t maxIndices = DefaultBatchSize * 3, - size_t maxVertices = DefaultBatchSize) - : PrimitiveBatchBase(device, maxIndices, maxVertices, sizeof(TVertex)) - { - } - - PrimitiveBatch(PrimitiveBatch&&) = default; - PrimitiveBatch& operator= (PrimitiveBatch&&) = default; - - PrimitiveBatch(PrimitiveBatch const&) = delete; - PrimitiveBatch& operator= (PrimitiveBatch const&) = delete; - - // Similar to the D3D9 API DrawPrimitiveUP. - void Draw(D3D_PRIMITIVE_TOPOLOGY topology, _In_reads_(vertexCount) TVertex const* vertices, size_t vertexCount) - { - void* mappedVertices; - - PrimitiveBatchBase::Draw(topology, false, nullptr, 0, vertexCount, &mappedVertices); - - memcpy(mappedVertices, vertices, vertexCount * sizeof(TVertex)); - } - - - // Similar to the D3D9 API DrawIndexedPrimitiveUP. - void DrawIndexed(D3D_PRIMITIVE_TOPOLOGY topology, _In_reads_(indexCount) uint16_t const* indices, size_t indexCount, _In_reads_(vertexCount) TVertex const* vertices, size_t vertexCount) - { - void* mappedVertices; - - PrimitiveBatchBase::Draw(topology, true, indices, indexCount, vertexCount, &mappedVertices); - - memcpy(mappedVertices, vertices, vertexCount * sizeof(TVertex)); - } - - - void DrawLine(TVertex const& v1, TVertex const& v2) - { - TVertex* mappedVertices; - - PrimitiveBatchBase::Draw(D3D_PRIMITIVE_TOPOLOGY_LINELIST, false, nullptr, 0, 2, reinterpret_cast(&mappedVertices)); - - mappedVertices[0] = v1; - mappedVertices[1] = v2; - } - - - void DrawTriangle(TVertex const& v1, TVertex const& v2, TVertex const& v3) - { - TVertex* mappedVertices; - - PrimitiveBatchBase::Draw(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, false, nullptr, 0, 3, reinterpret_cast(&mappedVertices)); - - mappedVertices[0] = v1; - mappedVertices[1] = v2; - mappedVertices[2] = v3; - } - - - void DrawQuad(TVertex const& v1, TVertex const& v2, TVertex const& v3, TVertex const& v4) - { - static const uint16_t quadIndices[] = { 0, 1, 2, 0, 2, 3 }; - - TVertex* mappedVertices; - - PrimitiveBatchBase::Draw(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, true, quadIndices, 6, 4, reinterpret_cast(&mappedVertices)); - - mappedVertices[0] = v1; - mappedVertices[1] = v2; - mappedVertices[2] = v3; - mappedVertices[3] = v4; - } - }; } diff --git a/Kits/DirectXTK12/Inc/SpriteBatch.h b/Kits/DirectXTK12/Inc/SpriteBatch.h index 4ffb653..1ad353d 100644 --- a/Kits/DirectXTK12/Inc/SpriteBatch.h +++ b/Kits/DirectXTK12/Inc/SpriteBatch.h @@ -37,118 +37,121 @@ namespace DirectX { class ResourceUploadBatch; - enum SpriteSortMode + inline namespace DX12 { - SpriteSortMode_Deferred, - SpriteSortMode_Immediate, - SpriteSortMode_Texture, - SpriteSortMode_BackToFront, - SpriteSortMode_FrontToBack, - }; - - enum SpriteEffects : uint32_t - { - SpriteEffects_None = 0, - SpriteEffects_FlipHorizontally = 1, - SpriteEffects_FlipVertically = 2, - SpriteEffects_FlipBoth = SpriteEffects_FlipHorizontally | SpriteEffects_FlipVertically, - }; - - class SpriteBatchPipelineStateDescription - { - public: - explicit SpriteBatchPipelineStateDescription( - const RenderTargetState& renderTarget, - _In_opt_ const D3D12_BLEND_DESC* blend = nullptr, - _In_opt_ const D3D12_DEPTH_STENCIL_DESC* depthStencil = nullptr, - _In_opt_ const D3D12_RASTERIZER_DESC* rasterizer = nullptr, - _In_opt_ const D3D12_GPU_DESCRIPTOR_HANDLE* isamplerDescriptor = nullptr) noexcept - : - blendDesc(blend ? *blend : s_DefaultBlendDesc), - depthStencilDesc(depthStencil ? *depthStencil : s_DefaultDepthStencilDesc), - rasterizerDesc(rasterizer ? *rasterizer : s_DefaultRasterizerDesc), - renderTargetState(renderTarget), - samplerDescriptor{}, - customRootSignature(nullptr), - customVertexShader{}, - customPixelShader{} + enum SpriteSortMode { - if (isamplerDescriptor) - this->samplerDescriptor = *isamplerDescriptor; - } + SpriteSortMode_Deferred, + SpriteSortMode_Immediate, + SpriteSortMode_Texture, + SpriteSortMode_BackToFront, + SpriteSortMode_FrontToBack, + }; - D3D12_BLEND_DESC blendDesc; - D3D12_DEPTH_STENCIL_DESC depthStencilDesc; - D3D12_RASTERIZER_DESC rasterizerDesc; - RenderTargetState renderTargetState; - D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor; - ID3D12RootSignature* customRootSignature; - D3D12_SHADER_BYTECODE customVertexShader; - D3D12_SHADER_BYTECODE customPixelShader; + enum SpriteEffects : uint32_t + { + SpriteEffects_None = 0, + SpriteEffects_FlipHorizontally = 1, + SpriteEffects_FlipVertically = 2, + SpriteEffects_FlipBoth = SpriteEffects_FlipHorizontally | SpriteEffects_FlipVertically, + }; - private: - static const D3D12_BLEND_DESC s_DefaultBlendDesc; - static const D3D12_RASTERIZER_DESC s_DefaultRasterizerDesc; - static const D3D12_DEPTH_STENCIL_DESC s_DefaultDepthStencilDesc; - }; + class SpriteBatchPipelineStateDescription + { + public: + explicit SpriteBatchPipelineStateDescription( + const RenderTargetState& renderTarget, + _In_opt_ const D3D12_BLEND_DESC* blend = nullptr, + _In_opt_ const D3D12_DEPTH_STENCIL_DESC* depthStencil = nullptr, + _In_opt_ const D3D12_RASTERIZER_DESC* rasterizer = nullptr, + _In_opt_ const D3D12_GPU_DESCRIPTOR_HANDLE* isamplerDescriptor = nullptr) noexcept + : + blendDesc(blend ? *blend : s_DefaultBlendDesc), + depthStencilDesc(depthStencil ? *depthStencil : s_DefaultDepthStencilDesc), + rasterizerDesc(rasterizer ? *rasterizer : s_DefaultRasterizerDesc), + renderTargetState(renderTarget), + samplerDescriptor{}, + customRootSignature(nullptr), + customVertexShader{}, + customPixelShader{} + { + if (isamplerDescriptor) + this->samplerDescriptor = *isamplerDescriptor; + } - class SpriteBatch - { - public: - SpriteBatch(_In_ ID3D12Device* device, ResourceUploadBatch& upload, - const SpriteBatchPipelineStateDescription& psoDesc, - _In_opt_ const D3D12_VIEWPORT* viewport = nullptr); + D3D12_BLEND_DESC blendDesc; + D3D12_DEPTH_STENCIL_DESC depthStencilDesc; + D3D12_RASTERIZER_DESC rasterizerDesc; + RenderTargetState renderTargetState; + D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor; + ID3D12RootSignature* customRootSignature; + D3D12_SHADER_BYTECODE customVertexShader; + D3D12_SHADER_BYTECODE customPixelShader; - SpriteBatch(SpriteBatch&&) noexcept; - SpriteBatch& operator= (SpriteBatch&&) noexcept; + private: + static const D3D12_BLEND_DESC s_DefaultBlendDesc; + static const D3D12_RASTERIZER_DESC s_DefaultRasterizerDesc; + static const D3D12_DEPTH_STENCIL_DESC s_DefaultDepthStencilDesc; + }; - SpriteBatch(SpriteBatch const&) = delete; - SpriteBatch& operator= (SpriteBatch const&) = delete; + class SpriteBatch + { + public: + SpriteBatch(_In_ ID3D12Device* device, ResourceUploadBatch& upload, + const SpriteBatchPipelineStateDescription& psoDesc, + _In_opt_ const D3D12_VIEWPORT* viewport = nullptr); - virtual ~SpriteBatch(); + SpriteBatch(SpriteBatch&&) noexcept; + SpriteBatch& operator= (SpriteBatch&&) noexcept; - // Begin/End a batch of sprite drawing operations. - void XM_CALLCONV Begin( - _In_ ID3D12GraphicsCommandList* commandList, - SpriteSortMode sortMode = SpriteSortMode_Deferred, - FXMMATRIX transformMatrix = MatrixIdentity); - void XM_CALLCONV Begin( - _In_ ID3D12GraphicsCommandList* commandList, - D3D12_GPU_DESCRIPTOR_HANDLE sampler, - SpriteSortMode sortMode = SpriteSortMode_Deferred, - FXMMATRIX transformMatrix = MatrixIdentity); - void __cdecl End(); + SpriteBatch(SpriteBatch const&) = delete; + SpriteBatch& operator= (SpriteBatch const&) = delete; - // Draw overloads specifying position, origin and scale as XMFLOAT2. - void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, XMFLOAT2 const& position, FXMVECTOR color = Colors::White); - void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, XMFLOAT2 const& position, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color = Colors::White, float rotation = 0, XMFLOAT2 const& origin = Float2Zero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); - void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, XMFLOAT2 const& position, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color, float rotation, XMFLOAT2 const& origin, XMFLOAT2 const& scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); + virtual ~SpriteBatch(); - // Draw overloads specifying position, origin and scale via the first two components of an XMVECTOR. - void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, FXMVECTOR position, FXMVECTOR color = Colors::White); - void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, FXMVECTOR position, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color = Colors::White, float rotation = 0, FXMVECTOR origin = g_XMZero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); - void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, FXMVECTOR position, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color, float rotation, FXMVECTOR origin, GXMVECTOR scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); + // Begin/End a batch of sprite drawing operations. + void XM_CALLCONV Begin( + _In_ ID3D12GraphicsCommandList* commandList, + SpriteSortMode sortMode = SpriteSortMode_Deferred, + FXMMATRIX transformMatrix = MatrixIdentity); + void XM_CALLCONV Begin( + _In_ ID3D12GraphicsCommandList* commandList, + D3D12_GPU_DESCRIPTOR_HANDLE sampler, + SpriteSortMode sortMode = SpriteSortMode_Deferred, + FXMMATRIX transformMatrix = MatrixIdentity); + void __cdecl End(); - // Draw overloads specifying position as a RECT. - void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, RECT const& destinationRectangle, FXMVECTOR color = Colors::White); - void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, RECT const& destinationRectangle, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color = Colors::White, float rotation = 0, XMFLOAT2 const& origin = Float2Zero, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); + // Draw overloads specifying position, origin and scale as XMFLOAT2. + void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, XMFLOAT2 const& position, FXMVECTOR color = Colors::White); + void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, XMFLOAT2 const& position, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color = Colors::White, float rotation = 0, XMFLOAT2 const& origin = Float2Zero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); + void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, XMFLOAT2 const& position, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color, float rotation, XMFLOAT2 const& origin, XMFLOAT2 const& scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); - // Rotation mode to be applied to the sprite transformation - #if defined(__dxgi1_2_h__) || defined(__d3d11_x_h__) || defined(__d3d12_x_h__) || defined(__XBOX_D3D12_X__) - void __cdecl SetRotation(DXGI_MODE_ROTATION mode); - DXGI_MODE_ROTATION __cdecl GetRotation() const noexcept; - #endif + // Draw overloads specifying position, origin and scale via the first two components of an XMVECTOR. + void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, FXMVECTOR position, FXMVECTOR color = Colors::White); + void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, FXMVECTOR position, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color = Colors::White, float rotation = 0, FXMVECTOR origin = g_XMZero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); + void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, FXMVECTOR position, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color, float rotation, FXMVECTOR origin, GXMVECTOR scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); - // Set viewport for sprite transformation - void __cdecl SetViewport(const D3D12_VIEWPORT& viewPort); + // Draw overloads specifying position as a RECT. + void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, RECT const& destinationRectangle, FXMVECTOR color = Colors::White); + void XM_CALLCONV Draw(D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, XMUINT2 const& textureSize, RECT const& destinationRectangle, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color = Colors::White, float rotation = 0, XMFLOAT2 const& origin = Float2Zero, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); - private: - // Private implementation. - struct Impl; + // Rotation mode to be applied to the sprite transformation + #if defined(__dxgi1_2_h__) || defined(__d3d11_x_h__) || defined(__d3d12_x_h__) || defined(__XBOX_D3D12_X__) + void __cdecl SetRotation(DXGI_MODE_ROTATION mode); + DXGI_MODE_ROTATION __cdecl GetRotation() const noexcept; + #endif - std::unique_ptr pImpl; + // Set viewport for sprite transformation + void __cdecl SetViewport(const D3D12_VIEWPORT& viewPort); - static const XMMATRIX MatrixIdentity; - static const XMFLOAT2 Float2Zero; - }; + private: + // Private implementation. + struct Impl; + + std::unique_ptr pImpl; + + static const XMMATRIX MatrixIdentity; + static const XMFLOAT2 Float2Zero; + }; + } } diff --git a/Kits/DirectXTK12/Inc/SpriteFont.h b/Kits/DirectXTK12/Inc/SpriteFont.h index f435c27..5f0c362 100644 --- a/Kits/DirectXTK12/Inc/SpriteFont.h +++ b/Kits/DirectXTK12/Inc/SpriteFont.h @@ -18,84 +18,87 @@ namespace DirectX { - class SpriteFont + inline namespace DX12 { - public: - struct Glyph; - - SpriteFont(ID3D12Device* device, ResourceUploadBatch& upload, - _In_z_ wchar_t const* fileName, - D3D12_CPU_DESCRIPTOR_HANDLE cpuDescriptorDest, D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptor, - bool forceSRGB = false); - SpriteFont(ID3D12Device* device, ResourceUploadBatch& upload, - _In_reads_bytes_(dataSize) uint8_t const* dataBlob, size_t dataSize, - D3D12_CPU_DESCRIPTOR_HANDLE cpuDescriptorDest, D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptor, - bool forceSRGB = false); - SpriteFont(D3D12_GPU_DESCRIPTOR_HANDLE texture, XMUINT2 textureSize, - _In_reads_(glyphCount) Glyph const* glyphs, size_t glyphCount, float lineSpacing); - - SpriteFont(SpriteFont&&) noexcept; - SpriteFont& operator= (SpriteFont&&) noexcept; - - SpriteFont(SpriteFont const&) = delete; - SpriteFont& operator= (SpriteFont const&) = delete; - - virtual ~SpriteFont(); - - // Wide-character / UTF-16LE - void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, XMFLOAT2 const& position, FXMVECTOR color = Colors::White, float rotation = 0, XMFLOAT2 const& origin = Float2Zero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; - void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, XMFLOAT2 const& position, FXMVECTOR color, float rotation, XMFLOAT2 const& origin, XMFLOAT2 const& scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; - void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, FXMVECTOR position, FXMVECTOR color = Colors::White, float rotation = 0, FXMVECTOR origin = g_XMZero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; - void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, FXMVECTOR position, FXMVECTOR color, float rotation, FXMVECTOR origin, GXMVECTOR scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; - - XMVECTOR XM_CALLCONV MeasureString(_In_z_ wchar_t const* text, bool ignoreWhitespace = true) const; - - RECT __cdecl MeasureDrawBounds(_In_z_ wchar_t const* text, XMFLOAT2 const& position, bool ignoreWhitespace = true) const; - RECT XM_CALLCONV MeasureDrawBounds(_In_z_ wchar_t const* text, FXMVECTOR position, bool ignoreWhitespace = true) const; - - // UTF-8 - void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ char const* text, XMFLOAT2 const& position, FXMVECTOR color = Colors::White, float rotation = 0, XMFLOAT2 const& origin = Float2Zero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; - void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ char const* text, XMFLOAT2 const& position, FXMVECTOR color, float rotation, XMFLOAT2 const& origin, XMFLOAT2 const& scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; - void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ char const* text, FXMVECTOR position, FXMVECTOR color = Colors::White, float rotation = 0, FXMVECTOR origin = g_XMZero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; - void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ char const* text, FXMVECTOR position, FXMVECTOR color, float rotation, FXMVECTOR origin, GXMVECTOR scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; - - XMVECTOR XM_CALLCONV MeasureString(_In_z_ char const* text, bool ignoreWhitespace = true) const; - - RECT __cdecl MeasureDrawBounds(_In_z_ char const* text, XMFLOAT2 const& position, bool ignoreWhitespace = true) const; - RECT XM_CALLCONV MeasureDrawBounds(_In_z_ char const* text, FXMVECTOR position, bool ignoreWhitespace = true) const; - - // Spacing properties - float __cdecl GetLineSpacing() const noexcept; - void __cdecl SetLineSpacing(float spacing); - - // Font properties - wchar_t __cdecl GetDefaultCharacter() const noexcept; - void __cdecl SetDefaultCharacter(wchar_t character); - - bool __cdecl ContainsCharacter(wchar_t character) const; - - // Custom layout/rendering - Glyph const* __cdecl FindGlyph(wchar_t character) const; - D3D12_GPU_DESCRIPTOR_HANDLE __cdecl GetSpriteSheet() const noexcept; - XMUINT2 __cdecl GetSpriteSheetSize() const noexcept; - - // Describes a single character glyph. - struct Glyph + class SpriteFont { - uint32_t Character; - RECT Subrect; - float XOffset; - float YOffset; - float XAdvance; + public: + struct Glyph; + + SpriteFont(ID3D12Device* device, ResourceUploadBatch& upload, + _In_z_ wchar_t const* fileName, + D3D12_CPU_DESCRIPTOR_HANDLE cpuDescriptorDest, D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptor, + bool forceSRGB = false); + SpriteFont(ID3D12Device* device, ResourceUploadBatch& upload, + _In_reads_bytes_(dataSize) uint8_t const* dataBlob, size_t dataSize, + D3D12_CPU_DESCRIPTOR_HANDLE cpuDescriptorDest, D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptor, + bool forceSRGB = false); + SpriteFont(D3D12_GPU_DESCRIPTOR_HANDLE texture, XMUINT2 textureSize, + _In_reads_(glyphCount) Glyph const* glyphs, size_t glyphCount, float lineSpacing); + + SpriteFont(SpriteFont&&) noexcept; + SpriteFont& operator= (SpriteFont&&) noexcept; + + SpriteFont(SpriteFont const&) = delete; + SpriteFont& operator= (SpriteFont const&) = delete; + + virtual ~SpriteFont(); + + // Wide-character / UTF-16LE + void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, XMFLOAT2 const& position, FXMVECTOR color = Colors::White, float rotation = 0, XMFLOAT2 const& origin = Float2Zero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; + void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, XMFLOAT2 const& position, FXMVECTOR color, float rotation, XMFLOAT2 const& origin, XMFLOAT2 const& scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; + void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, FXMVECTOR position, FXMVECTOR color = Colors::White, float rotation = 0, FXMVECTOR origin = g_XMZero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; + void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, FXMVECTOR position, FXMVECTOR color, float rotation, FXMVECTOR origin, GXMVECTOR scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; + + XMVECTOR XM_CALLCONV MeasureString(_In_z_ wchar_t const* text, bool ignoreWhitespace = true) const; + + RECT __cdecl MeasureDrawBounds(_In_z_ wchar_t const* text, XMFLOAT2 const& position, bool ignoreWhitespace = true) const; + RECT XM_CALLCONV MeasureDrawBounds(_In_z_ wchar_t const* text, FXMVECTOR position, bool ignoreWhitespace = true) const; + + // UTF-8 + void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ char const* text, XMFLOAT2 const& position, FXMVECTOR color = Colors::White, float rotation = 0, XMFLOAT2 const& origin = Float2Zero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; + void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ char const* text, XMFLOAT2 const& position, FXMVECTOR color, float rotation, XMFLOAT2 const& origin, XMFLOAT2 const& scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; + void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ char const* text, FXMVECTOR position, FXMVECTOR color = Colors::White, float rotation = 0, FXMVECTOR origin = g_XMZero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; + void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ char const* text, FXMVECTOR position, FXMVECTOR color, float rotation, FXMVECTOR origin, GXMVECTOR scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; + + XMVECTOR XM_CALLCONV MeasureString(_In_z_ char const* text, bool ignoreWhitespace = true) const; + + RECT __cdecl MeasureDrawBounds(_In_z_ char const* text, XMFLOAT2 const& position, bool ignoreWhitespace = true) const; + RECT XM_CALLCONV MeasureDrawBounds(_In_z_ char const* text, FXMVECTOR position, bool ignoreWhitespace = true) const; + + // Spacing properties + float __cdecl GetLineSpacing() const noexcept; + void __cdecl SetLineSpacing(float spacing); + + // Font properties + wchar_t __cdecl GetDefaultCharacter() const noexcept; + void __cdecl SetDefaultCharacter(wchar_t character); + + bool __cdecl ContainsCharacter(wchar_t character) const; + + // Custom layout/rendering + Glyph const* __cdecl FindGlyph(wchar_t character) const; + D3D12_GPU_DESCRIPTOR_HANDLE __cdecl GetSpriteSheet() const noexcept; + XMUINT2 __cdecl GetSpriteSheetSize() const noexcept; + + // Describes a single character glyph. + struct Glyph + { + uint32_t Character; + RECT Subrect; + float XOffset; + float YOffset; + float XAdvance; + }; + + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + + static const XMFLOAT2 Float2Zero; }; - - - private: - // Private implementation. - class Impl; - - std::unique_ptr pImpl; - - static const XMFLOAT2 Float2Zero; - }; + } } diff --git a/Kits/DirectXTK12/Inc/VertexTypes.h b/Kits/DirectXTK12/Inc/VertexTypes.h index e1c3892..78c14db 100644 --- a/Kits/DirectXTK12/Inc/VertexTypes.h +++ b/Kits/DirectXTK12/Inc/VertexTypes.h @@ -25,333 +25,336 @@ namespace DirectX { + inline namespace DX12 + { // Vertex struct holding position information. - struct VertexPosition - { - VertexPosition() = default; - - VertexPosition(const VertexPosition&) = default; - VertexPosition& operator=(const VertexPosition&) = default; - - VertexPosition(VertexPosition&&) = default; - VertexPosition& operator=(VertexPosition&&) = default; - - VertexPosition(XMFLOAT3 const& iposition) noexcept - : position(iposition) + struct VertexPosition { - } + VertexPosition() = default; - VertexPosition(FXMVECTOR iposition) noexcept + VertexPosition(const VertexPosition&) = default; + VertexPosition& operator=(const VertexPosition&) = default; + + VertexPosition(VertexPosition&&) = default; + VertexPosition& operator=(VertexPosition&&) = default; + + VertexPosition(XMFLOAT3 const& iposition) noexcept + : position(iposition) + { + } + + VertexPosition(FXMVECTOR iposition) noexcept + { + XMStoreFloat3(&this->position, iposition); + } + + XMFLOAT3 position; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static constexpr unsigned int InputElementCount = 1; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; + + + // Vertex struct holding position and color information. + struct VertexPositionColor { - XMStoreFloat3(&this->position, iposition); - } + VertexPositionColor() = default; - XMFLOAT3 position; + VertexPositionColor(const VertexPositionColor&) = default; + VertexPositionColor& operator=(const VertexPositionColor&) = default; - static const D3D12_INPUT_LAYOUT_DESC InputLayout; + VertexPositionColor(VertexPositionColor&&) = default; + VertexPositionColor& operator=(VertexPositionColor&&) = default; - private: - static constexpr unsigned int InputElementCount = 1; - static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; - }; + VertexPositionColor(XMFLOAT3 const& iposition, XMFLOAT4 const& icolor) noexcept + : position(iposition), + color(icolor) + { + } + + VertexPositionColor(FXMVECTOR iposition, FXMVECTOR icolor) noexcept + { + XMStoreFloat3(&this->position, iposition); + XMStoreFloat4(&this->color, icolor); + } + + XMFLOAT3 position; + XMFLOAT4 color; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static constexpr unsigned int InputElementCount = 2; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; - // Vertex struct holding position and color information. - struct VertexPositionColor - { - VertexPositionColor() = default; - - VertexPositionColor(const VertexPositionColor&) = default; - VertexPositionColor& operator=(const VertexPositionColor&) = default; - - VertexPositionColor(VertexPositionColor&&) = default; - VertexPositionColor& operator=(VertexPositionColor&&) = default; - - VertexPositionColor(XMFLOAT3 const& iposition, XMFLOAT4 const& icolor) noexcept - : position(iposition), - color(icolor) + // Vertex struct holding position and texture mapping information. + struct VertexPositionTexture { - } + VertexPositionTexture() = default; - VertexPositionColor(FXMVECTOR iposition, FXMVECTOR icolor) noexcept + VertexPositionTexture(const VertexPositionTexture&) = default; + VertexPositionTexture& operator=(const VertexPositionTexture&) = default; + + VertexPositionTexture(VertexPositionTexture&&) = default; + VertexPositionTexture& operator=(VertexPositionTexture&&) = default; + + VertexPositionTexture(XMFLOAT3 const& iposition, XMFLOAT2 const& itextureCoordinate) noexcept + : position(iposition), + textureCoordinate(itextureCoordinate) + { + } + + VertexPositionTexture(FXMVECTOR iposition, FXMVECTOR itextureCoordinate) noexcept + { + XMStoreFloat3(&this->position, iposition); + XMStoreFloat2(&this->textureCoordinate, itextureCoordinate); + } + + XMFLOAT3 position; + XMFLOAT2 textureCoordinate; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static constexpr unsigned int InputElementCount = 2; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; + + + // Vertex struct holding position and dual texture mapping information. + struct VertexPositionDualTexture { - XMStoreFloat3(&this->position, iposition); - XMStoreFloat4(&this->color, icolor); - } + VertexPositionDualTexture() = default; - XMFLOAT3 position; - XMFLOAT4 color; + VertexPositionDualTexture(const VertexPositionDualTexture&) = default; + VertexPositionDualTexture& operator=(const VertexPositionDualTexture&) = default; - static const D3D12_INPUT_LAYOUT_DESC InputLayout; + VertexPositionDualTexture(VertexPositionDualTexture&&) = default; + VertexPositionDualTexture& operator=(VertexPositionDualTexture&&) = default; - private: - static constexpr unsigned int InputElementCount = 2; - static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; - }; + VertexPositionDualTexture( + XMFLOAT3 const& iposition, + XMFLOAT2 const& itextureCoordinate0, + XMFLOAT2 const& itextureCoordinate1) noexcept + : position(iposition), + textureCoordinate0(itextureCoordinate0), + textureCoordinate1(itextureCoordinate1) + { + } + + VertexPositionDualTexture( + FXMVECTOR iposition, + FXMVECTOR itextureCoordinate0, + FXMVECTOR itextureCoordinate1) noexcept + { + XMStoreFloat3(&this->position, iposition); + XMStoreFloat2(&this->textureCoordinate0, itextureCoordinate0); + XMStoreFloat2(&this->textureCoordinate1, itextureCoordinate1); + } + + XMFLOAT3 position; + XMFLOAT2 textureCoordinate0; + XMFLOAT2 textureCoordinate1; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static constexpr unsigned int InputElementCount = 3; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; - // Vertex struct holding position and texture mapping information. - struct VertexPositionTexture - { - VertexPositionTexture() = default; - - VertexPositionTexture(const VertexPositionTexture&) = default; - VertexPositionTexture& operator=(const VertexPositionTexture&) = default; - - VertexPositionTexture(VertexPositionTexture&&) = default; - VertexPositionTexture& operator=(VertexPositionTexture&&) = default; - - VertexPositionTexture(XMFLOAT3 const& iposition, XMFLOAT2 const& itextureCoordinate) noexcept - : position(iposition), - textureCoordinate(itextureCoordinate) + // Vertex struct holding position and normal vector. + struct VertexPositionNormal { - } + VertexPositionNormal() = default; - VertexPositionTexture(FXMVECTOR iposition, FXMVECTOR itextureCoordinate) noexcept + VertexPositionNormal(const VertexPositionNormal&) = default; + VertexPositionNormal& operator=(const VertexPositionNormal&) = default; + + VertexPositionNormal(VertexPositionNormal&&) = default; + VertexPositionNormal& operator=(VertexPositionNormal&&) = default; + + VertexPositionNormal(XMFLOAT3 const& iposition, XMFLOAT3 const& inormal) noexcept + : position(iposition), + normal(inormal) + { + } + + VertexPositionNormal(FXMVECTOR iposition, FXMVECTOR inormal) noexcept + { + XMStoreFloat3(&this->position, iposition); + XMStoreFloat3(&this->normal, inormal); + } + + XMFLOAT3 position; + XMFLOAT3 normal; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static constexpr unsigned int InputElementCount = 2; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; + + + // Vertex struct holding position, color, and texture mapping information. + struct VertexPositionColorTexture { - XMStoreFloat3(&this->position, iposition); - XMStoreFloat2(&this->textureCoordinate, itextureCoordinate); - } + VertexPositionColorTexture() = default; - XMFLOAT3 position; - XMFLOAT2 textureCoordinate; + VertexPositionColorTexture(const VertexPositionColorTexture&) = default; + VertexPositionColorTexture& operator=(const VertexPositionColorTexture&) = default; - static const D3D12_INPUT_LAYOUT_DESC InputLayout; + VertexPositionColorTexture(VertexPositionColorTexture&&) = default; + VertexPositionColorTexture& operator=(VertexPositionColorTexture&&) = default; - private: - static constexpr unsigned int InputElementCount = 2; - static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; - }; + VertexPositionColorTexture(XMFLOAT3 const& iposition, XMFLOAT4 const& icolor, XMFLOAT2 const& itextureCoordinate) noexcept + : position(iposition), + color(icolor), + textureCoordinate(itextureCoordinate) + { + } + + VertexPositionColorTexture(FXMVECTOR iposition, FXMVECTOR icolor, FXMVECTOR itextureCoordinate) noexcept + { + XMStoreFloat3(&this->position, iposition); + XMStoreFloat4(&this->color, icolor); + XMStoreFloat2(&this->textureCoordinate, itextureCoordinate); + } + + XMFLOAT3 position; + XMFLOAT4 color; + XMFLOAT2 textureCoordinate; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static constexpr unsigned int InputElementCount = 3; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; - // Vertex struct holding position and dual texture mapping information. - struct VertexPositionDualTexture - { - VertexPositionDualTexture() = default; - - VertexPositionDualTexture(const VertexPositionDualTexture&) = default; - VertexPositionDualTexture& operator=(const VertexPositionDualTexture&) = default; - - VertexPositionDualTexture(VertexPositionDualTexture&&) = default; - VertexPositionDualTexture& operator=(VertexPositionDualTexture&&) = default; - - VertexPositionDualTexture( - XMFLOAT3 const& iposition, - XMFLOAT2 const& itextureCoordinate0, - XMFLOAT2 const& itextureCoordinate1) noexcept - : position(iposition), - textureCoordinate0(itextureCoordinate0), - textureCoordinate1(itextureCoordinate1) + // Vertex struct holding position, normal vector, and color information. + struct VertexPositionNormalColor { - } + VertexPositionNormalColor() = default; - VertexPositionDualTexture( - FXMVECTOR iposition, - FXMVECTOR itextureCoordinate0, - FXMVECTOR itextureCoordinate1) noexcept + VertexPositionNormalColor(const VertexPositionNormalColor&) = default; + VertexPositionNormalColor& operator=(const VertexPositionNormalColor&) = default; + + VertexPositionNormalColor(VertexPositionNormalColor&&) = default; + VertexPositionNormalColor& operator=(VertexPositionNormalColor&&) = default; + + VertexPositionNormalColor(XMFLOAT3 const& iposition, XMFLOAT3 const& inormal, XMFLOAT4 const& icolor) noexcept + : position(iposition), + normal(inormal), + color(icolor) + { + } + + VertexPositionNormalColor(FXMVECTOR iposition, FXMVECTOR inormal, FXMVECTOR icolor) noexcept + { + XMStoreFloat3(&this->position, iposition); + XMStoreFloat3(&this->normal, inormal); + XMStoreFloat4(&this->color, icolor); + } + + XMFLOAT3 position; + XMFLOAT3 normal; + XMFLOAT4 color; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static constexpr unsigned int InputElementCount = 3; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; + + + // Vertex struct holding position, normal vector, and texture mapping information. + struct VertexPositionNormalTexture { - XMStoreFloat3(&this->position, iposition); - XMStoreFloat2(&this->textureCoordinate0, itextureCoordinate0); - XMStoreFloat2(&this->textureCoordinate1, itextureCoordinate1); - } + VertexPositionNormalTexture() = default; - XMFLOAT3 position; - XMFLOAT2 textureCoordinate0; - XMFLOAT2 textureCoordinate1; + VertexPositionNormalTexture(const VertexPositionNormalTexture&) = default; + VertexPositionNormalTexture& operator=(const VertexPositionNormalTexture&) = default; - static const D3D12_INPUT_LAYOUT_DESC InputLayout; + VertexPositionNormalTexture(VertexPositionNormalTexture&&) = default; + VertexPositionNormalTexture& operator=(VertexPositionNormalTexture&&) = default; - private: - static constexpr unsigned int InputElementCount = 3; - static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; - }; + VertexPositionNormalTexture(XMFLOAT3 const& iposition, XMFLOAT3 const& inormal, XMFLOAT2 const& itextureCoordinate) noexcept + : position(iposition), + normal(inormal), + textureCoordinate(itextureCoordinate) + { + } + + VertexPositionNormalTexture(FXMVECTOR iposition, FXMVECTOR inormal, FXMVECTOR itextureCoordinate) noexcept + { + XMStoreFloat3(&this->position, iposition); + XMStoreFloat3(&this->normal, inormal); + XMStoreFloat2(&this->textureCoordinate, itextureCoordinate); + } + + XMFLOAT3 position; + XMFLOAT3 normal; + XMFLOAT2 textureCoordinate; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static constexpr unsigned int InputElementCount = 3; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; - // Vertex struct holding position and normal vector. - struct VertexPositionNormal - { - VertexPositionNormal() = default; - - VertexPositionNormal(const VertexPositionNormal&) = default; - VertexPositionNormal& operator=(const VertexPositionNormal&) = default; - - VertexPositionNormal(VertexPositionNormal&&) = default; - VertexPositionNormal& operator=(VertexPositionNormal&&) = default; - - VertexPositionNormal(XMFLOAT3 const& iposition, XMFLOAT3 const& inormal) noexcept - : position(iposition), - normal(inormal) + // Vertex struct holding position, normal vector, color, and texture mapping information. + struct VertexPositionNormalColorTexture { - } + VertexPositionNormalColorTexture() = default; - VertexPositionNormal(FXMVECTOR iposition, FXMVECTOR inormal) noexcept - { - XMStoreFloat3(&this->position, iposition); - XMStoreFloat3(&this->normal, inormal); - } + VertexPositionNormalColorTexture(const VertexPositionNormalColorTexture&) = default; + VertexPositionNormalColorTexture& operator=(const VertexPositionNormalColorTexture&) = default; - XMFLOAT3 position; - XMFLOAT3 normal; + VertexPositionNormalColorTexture(VertexPositionNormalColorTexture&&) = default; + VertexPositionNormalColorTexture& operator=(VertexPositionNormalColorTexture&&) = default; - static const D3D12_INPUT_LAYOUT_DESC InputLayout; + VertexPositionNormalColorTexture( + XMFLOAT3 const& iposition, + XMFLOAT3 const& inormal, + XMFLOAT4 const& icolor, + XMFLOAT2 const& itextureCoordinate) noexcept + : position(iposition), + normal(inormal), + color(icolor), + textureCoordinate(itextureCoordinate) + { + } - private: - static constexpr unsigned int InputElementCount = 2; - static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; - }; + VertexPositionNormalColorTexture(FXMVECTOR iposition, FXMVECTOR inormal, FXMVECTOR icolor, CXMVECTOR itextureCoordinate) noexcept + { + XMStoreFloat3(&this->position, iposition); + XMStoreFloat3(&this->normal, inormal); + XMStoreFloat4(&this->color, icolor); + XMStoreFloat2(&this->textureCoordinate, itextureCoordinate); + } + XMFLOAT3 position; + XMFLOAT3 normal; + XMFLOAT4 color; + XMFLOAT2 textureCoordinate; - // Vertex struct holding position, color, and texture mapping information. - struct VertexPositionColorTexture - { - VertexPositionColorTexture() = default; + static const D3D12_INPUT_LAYOUT_DESC InputLayout; - VertexPositionColorTexture(const VertexPositionColorTexture&) = default; - VertexPositionColorTexture& operator=(const VertexPositionColorTexture&) = default; - - VertexPositionColorTexture(VertexPositionColorTexture&&) = default; - VertexPositionColorTexture& operator=(VertexPositionColorTexture&&) = default; - - VertexPositionColorTexture(XMFLOAT3 const& iposition, XMFLOAT4 const& icolor, XMFLOAT2 const& itextureCoordinate) noexcept - : position(iposition), - color(icolor), - textureCoordinate(itextureCoordinate) - { - } - - VertexPositionColorTexture(FXMVECTOR iposition, FXMVECTOR icolor, FXMVECTOR itextureCoordinate) noexcept - { - XMStoreFloat3(&this->position, iposition); - XMStoreFloat4(&this->color, icolor); - XMStoreFloat2(&this->textureCoordinate, itextureCoordinate); - } - - XMFLOAT3 position; - XMFLOAT4 color; - XMFLOAT2 textureCoordinate; - - static const D3D12_INPUT_LAYOUT_DESC InputLayout; - - private: - static constexpr unsigned int InputElementCount = 3; - static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; - }; - - - // Vertex struct holding position, normal vector, and color information. - struct VertexPositionNormalColor - { - VertexPositionNormalColor() = default; - - VertexPositionNormalColor(const VertexPositionNormalColor&) = default; - VertexPositionNormalColor& operator=(const VertexPositionNormalColor&) = default; - - VertexPositionNormalColor(VertexPositionNormalColor&&) = default; - VertexPositionNormalColor& operator=(VertexPositionNormalColor&&) = default; - - VertexPositionNormalColor(XMFLOAT3 const& iposition, XMFLOAT3 const& inormal, XMFLOAT4 const& icolor) noexcept - : position(iposition), - normal(inormal), - color(icolor) - { - } - - VertexPositionNormalColor(FXMVECTOR iposition, FXMVECTOR inormal, FXMVECTOR icolor) noexcept - { - XMStoreFloat3(&this->position, iposition); - XMStoreFloat3(&this->normal, inormal); - XMStoreFloat4(&this->color, icolor); - } - - XMFLOAT3 position; - XMFLOAT3 normal; - XMFLOAT4 color; - - static const D3D12_INPUT_LAYOUT_DESC InputLayout; - - private: - static constexpr unsigned int InputElementCount = 3; - static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; - }; - - - // Vertex struct holding position, normal vector, and texture mapping information. - struct VertexPositionNormalTexture - { - VertexPositionNormalTexture() = default; - - VertexPositionNormalTexture(const VertexPositionNormalTexture&) = default; - VertexPositionNormalTexture& operator=(const VertexPositionNormalTexture&) = default; - - VertexPositionNormalTexture(VertexPositionNormalTexture&&) = default; - VertexPositionNormalTexture& operator=(VertexPositionNormalTexture&&) = default; - - VertexPositionNormalTexture(XMFLOAT3 const& iposition, XMFLOAT3 const& inormal, XMFLOAT2 const& itextureCoordinate) noexcept - : position(iposition), - normal(inormal), - textureCoordinate(itextureCoordinate) - { - } - - VertexPositionNormalTexture(FXMVECTOR iposition, FXMVECTOR inormal, FXMVECTOR itextureCoordinate) noexcept - { - XMStoreFloat3(&this->position, iposition); - XMStoreFloat3(&this->normal, inormal); - XMStoreFloat2(&this->textureCoordinate, itextureCoordinate); - } - - XMFLOAT3 position; - XMFLOAT3 normal; - XMFLOAT2 textureCoordinate; - - static const D3D12_INPUT_LAYOUT_DESC InputLayout; - - private: - static constexpr unsigned int InputElementCount = 3; - static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; - }; - - - // Vertex struct holding position, normal vector, color, and texture mapping information. - struct VertexPositionNormalColorTexture - { - VertexPositionNormalColorTexture() = default; - - VertexPositionNormalColorTexture(const VertexPositionNormalColorTexture&) = default; - VertexPositionNormalColorTexture& operator=(const VertexPositionNormalColorTexture&) = default; - - VertexPositionNormalColorTexture(VertexPositionNormalColorTexture&&) = default; - VertexPositionNormalColorTexture& operator=(VertexPositionNormalColorTexture&&) = default; - - VertexPositionNormalColorTexture( - XMFLOAT3 const& iposition, - XMFLOAT3 const& inormal, - XMFLOAT4 const& icolor, - XMFLOAT2 const& itextureCoordinate) noexcept - : position(iposition), - normal(inormal), - color(icolor), - textureCoordinate(itextureCoordinate) - { - } - - VertexPositionNormalColorTexture(FXMVECTOR iposition, FXMVECTOR inormal, FXMVECTOR icolor, CXMVECTOR itextureCoordinate) noexcept - { - XMStoreFloat3(&this->position, iposition); - XMStoreFloat3(&this->normal, inormal); - XMStoreFloat4(&this->color, icolor); - XMStoreFloat2(&this->textureCoordinate, itextureCoordinate); - } - - XMFLOAT3 position; - XMFLOAT3 normal; - XMFLOAT4 color; - XMFLOAT2 textureCoordinate; - - static const D3D12_INPUT_LAYOUT_DESC InputLayout; - - private: - static constexpr unsigned int InputElementCount = 4; - static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; - }; + private: + static constexpr unsigned int InputElementCount = 4; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; + } } diff --git a/Kits/DirectXTK12/Inc/WICTextureLoader.h b/Kits/DirectXTK12/Inc/WICTextureLoader.h index 92824db..d09406b 100644 --- a/Kits/DirectXTK12/Inc/WICTextureLoader.h +++ b/Kits/DirectXTK12/Inc/WICTextureLoader.h @@ -39,18 +39,21 @@ namespace DirectX { - enum WIC_LOADER_FLAGS : uint32_t + inline namespace DX12 { - WIC_LOADER_DEFAULT = 0, - WIC_LOADER_FORCE_SRGB = 0x1, - WIC_LOADER_IGNORE_SRGB = 0x2, - WIC_LOADER_SRGB_DEFAULT = 0x4, - WIC_LOADER_MIP_AUTOGEN = 0x8, - WIC_LOADER_MIP_RESERVE = 0x10, - WIC_LOADER_FIT_POW2 = 0x20, - WIC_LOADER_MAKE_SQUARE = 0x40, - WIC_LOADER_FORCE_RGBA32 = 0x80, - }; + enum WIC_LOADER_FLAGS : uint32_t + { + WIC_LOADER_DEFAULT = 0, + WIC_LOADER_FORCE_SRGB = 0x1, + WIC_LOADER_IGNORE_SRGB = 0x2, + WIC_LOADER_SRGB_DEFAULT = 0x4, + WIC_LOADER_MIP_AUTOGEN = 0x8, + WIC_LOADER_MIP_RESERVE = 0x10, + WIC_LOADER_FIT_POW2 = 0x20, + WIC_LOADER_MAKE_SQUARE = 0x40, + WIC_LOADER_FORCE_RGBA32 = 0x80, + }; + } class ResourceUploadBatch; @@ -137,7 +140,10 @@ namespace DirectX #pragma clang diagnostic ignored "-Wdeprecated-dynamic-exception-spec" #endif - DEFINE_ENUM_FLAG_OPERATORS(WIC_LOADER_FLAGS); + inline namespace DX12 + { + DEFINE_ENUM_FLAG_OPERATORS(WIC_LOADER_FLAGS); + } #ifdef __clang__ #pragma clang diagnostic pop diff --git a/Kits/DirectXTK12/README.md b/Kits/DirectXTK12/README.md index c920ab8..800ce7b 100644 --- a/Kits/DirectXTK12/README.md +++ b/Kits/DirectXTK12/README.md @@ -6,11 +6,11 @@ http://go.microsoft.com/fwlink/?LinkID=615561 Copyright (c) Microsoft Corporation. -**June 9, 2022** +**October 17, 2022** This package contains the "DirectX Tool Kit", a collection of helper classes for writing Direct3D 12 C++ code for Universal Windows Platform (UWP) apps for Windows 11 / Windows 10, game titles for Xbox Series X\|S / Xbox One, and Win32 desktop applications for Windows 11 / Windows 10. -This code is designed to build with Visual Studio 2019 (16.9 or later), Visual Studio 2022, or clang for Windows v11 or later. Use of the Windows 10 May 2020 Update SDK ([19041](https://walbourn.github.io/windows-10-may-2020-update-sdk/)) or later is required. +This code is designed to build with Visual Studio 2019 (16.11), Visual Studio 2022, or clang for Windows v11 or later. Use of the Windows 10 May 2020 Update SDK ([19041](https://walbourn.github.io/windows-10-may-2020-update-sdk/)) or later is required. These components are designed to work without requiring any content from the legacy DirectX SDK. For details, see [Where is the DirectX SDK?](https://aka.ms/dxsdk). @@ -80,6 +80,8 @@ For the latest version of DirectXTK12, bug reports, etc. please visit the projec ## Release Notes +* As of the September 2022 release, the library makes use of C++11 inline namespaces for differing types that have the same names in the DirectX 11 and DirectX 12 version of the *DirectX Tool Kit*. This provides a link-unique name such as ``DirectX::DX12::SpriteBatch`` that will appear in linker output messages. In most use cases, however, there is no need to add explicit ``DX12`` namespace resolution in client code. + * As of the March 2022 release, legacy Xbox One XDK support requires the XDK April 2018 release or later. Upgrading to the Microsoft GDKX is strongly recommended. * In the June 2021 release or later, the VS 2019 projects of this library build the HLSL shaders with Shader Model 6 via DXC. Since the NuGet still builds using VS 2017, the build-in shaders in that version are currently Shader Model 5.1. See [this wiki page](https://github.com/microsoft/DirectXTK12/wiki/Shader-Model-6) for more information. The Microsoft GDK projects always use Shader Model 6. @@ -116,7 +118,7 @@ This project may contain trademarks or logos for projects, products, or services ## Credits -The _DirectX Tool Kit for DirectX 11_ is the work of Shawn Hargreaves and Chuck Walbourn, with contributions from Aaron Rodriguez Hernandez, and Dani Roman. +The _DirectX Tool Kit for DirectX 11_ is the work of Shawn Hargreaves and Chuck Walbourn, with contributions from Aaron Rodriguez Hernandez and Dani Roman. The _DirectX Tool Kit for DirectX 12_ is the work of Pete Lewis, Justin Saunders, and Chuck Walbourn based heavily on the DirectX Tool Kit for DirectX 11. diff --git a/Kits/DirectXTK12/Src/BasicPostProcess.cpp b/Kits/DirectXTK12/Src/BasicPostProcess.cpp index 46f0bf0..ac31c63 100644 --- a/Kits/DirectXTK12/Src/BasicPostProcess.cpp +++ b/Kits/DirectXTK12/Src/BasicPostProcess.cpp @@ -572,7 +572,12 @@ void BasicPostProcess::SetSourceTexture(D3D12_GPU_DESCRIPTOR_HANDLE srvDescripto if (resource) { + #if defined(_MSC_VER) || !defined(_WIN32) const auto desc = resource->GetDesc(); + #else + D3D12_RESOURCE_DESC tmpDesc; + const auto& desc = *resource->GetDesc(&tmpDesc); + #endif pImpl->texWidth = static_cast(desc.Width); pImpl->texHeight = desc.Height; } diff --git a/Kits/DirectXTK12/Src/DDSTextureLoader.cpp b/Kits/DirectXTK12/Src/DDSTextureLoader.cpp index 7b0594b..6dc5360 100644 --- a/Kits/DirectXTK12/Src/DDSTextureLoader.cpp +++ b/Kits/DirectXTK12/Src/DDSTextureLoader.cpp @@ -239,6 +239,10 @@ namespace { format = MakeSRGB(format); } + else if (loadFlags & DDS_LOADER_IGNORE_SRGB) + { + format = MakeLinear(format); + } D3D12_RESOURCE_DESC desc = {}; desc.Width = static_cast(width); @@ -871,7 +875,14 @@ HRESULT DirectX::CreateDDSTextureFromMemoryEx( D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); // If it's missing mips, let's generate them - if ((loadFlags & DDS_LOADER_MIP_AUTOGEN) && subresources.size() != (*texture)->GetDesc().MipLevels) + #if defined(_MSC_VER) || !defined(_WIN32) + const size_t mipLevels = (*texture)->GetDesc().MipLevels; + #else + D3D12_RESOURCE_DESC tmpDesc; + const size_t mipLevels = (*texture)->GetDesc(&tmpDesc)->MipLevels; + #endif + + if ((loadFlags & DDS_LOADER_MIP_AUTOGEN) && subresources.size() != mipLevels) { resourceUpload.GenerateMips(*texture); } @@ -986,7 +997,14 @@ HRESULT DirectX::CreateDDSTextureFromFileEx( D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); // If it's missing mips, let's generate them - if ((loadFlags & DDS_LOADER_MIP_AUTOGEN) && subresources.size() != (*texture)->GetDesc().MipLevels) + #if defined(_MSC_VER) || !defined(_WIN32) + const size_t mipLevels = (*texture)->GetDesc().MipLevels; + #else + D3D12_RESOURCE_DESC tmpDesc; + const size_t mipLevels = (*texture)->GetDesc(&tmpDesc)->MipLevels; + #endif + + if ((loadFlags & DDS_LOADER_MIP_AUTOGEN) && subresources.size() != mipLevels) { resourceUpload.GenerateMips(*texture); } diff --git a/Kits/DirectXTK12/Src/DescriptorHeap.cpp b/Kits/DirectXTK12/Src/DescriptorHeap.cpp index ab0f87f..3c912ee 100644 --- a/Kits/DirectXTK12/Src/DescriptorHeap.cpp +++ b/Kits/DirectXTK12/Src/DescriptorHeap.cpp @@ -37,9 +37,15 @@ DescriptorHeap::DescriptorHeap( ID3D12DescriptorHeap* pExistingHeap) noexcept : m_pHeap(pExistingHeap) { +#if defined(_MSC_VER) || !defined(_WIN32) m_hCPU = pExistingHeap->GetCPUDescriptorHandleForHeapStart(); m_hGPU = pExistingHeap->GetGPUDescriptorHandleForHeapStart(); m_desc = pExistingHeap->GetDesc(); +#else + std::ignore = pExistingHeap->GetCPUDescriptorHandleForHeapStart(&m_hCPU); + std::ignore = pExistingHeap->GetGPUDescriptorHandleForHeapStart(&m_hGPU); + std::ignore = pExistingHeap->GetDesc(&m_desc); +#endif ComPtr device; pExistingHeap->GetDevice(IID_GRAPHICS_PPV_ARGS(device.GetAddressOf())); @@ -168,11 +174,19 @@ void DescriptorHeap::Create( SetDebugObjectName(m_pHeap.Get(), L"DescriptorHeap"); + #if defined(_MSC_VER) || !defined(_WIN32) m_hCPU = m_pHeap->GetCPUDescriptorHandleForHeapStart(); - if (pDesc->Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE) + { m_hGPU = m_pHeap->GetGPUDescriptorHandleForHeapStart(); - + } + #else + std::ignore = m_pHeap->GetCPUDescriptorHandleForHeapStart(&m_hCPU); + if (pDesc->Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE) + { + std::ignore = m_pHeap->GetGPUDescriptorHandleForHeapStart(&m_hGPU); + } + #endif } } diff --git a/Kits/DirectXTK12/Src/DirectXHelpers.cpp b/Kits/DirectXTK12/Src/DirectXHelpers.cpp index 424ef7d..1364a2f 100644 --- a/Kits/DirectXTK12/Src/DirectXHelpers.cpp +++ b/Kits/DirectXTK12/Src/DirectXHelpers.cpp @@ -21,7 +21,12 @@ void DirectX::CreateShaderResourceView( D3D12_CPU_DESCRIPTOR_HANDLE srvDescriptor, bool isCubeMap) { +#if defined(_MSC_VER) || !defined(_WIN32) const auto desc = tex->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& desc = *tex->GetDesc(&tmpDesc); +#endif D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; srvDesc.Format = desc.Format; diff --git a/Kits/DirectXTK12/Src/EffectCommon.h b/Kits/DirectXTK12/Src/EffectCommon.h index 95a48d3..c30aa67 100644 --- a/Kits/DirectXTK12/Src/EffectCommon.h +++ b/Kits/DirectXTK12/Src/EffectCommon.h @@ -28,13 +28,16 @@ namespace DirectX { - // Internal effect flags - namespace EffectFlags + inline namespace DX12 { - constexpr int PerPixelLightingBit = 0x04; - } + // Internal effect flags + namespace EffectFlags + { + constexpr int PerPixelLightingBit = 0x04; + } - static_assert(((EffectFlags::PerPixelLighting)& EffectFlags::PerPixelLightingBit) != 0, "PerPixelLighting enum flags mismatch"); + static_assert(((EffectFlags::PerPixelLighting)& EffectFlags::PerPixelLightingBit) != 0, "PerPixelLighting enum flags mismatch"); + } // Bitfield tracks which derived parameter values need to be recomputed. namespace EffectDirtyFlags diff --git a/Kits/DirectXTK12/Src/EffectFactory.cpp b/Kits/DirectXTK12/Src/EffectFactory.cpp index d20bea6..aa24df9 100644 --- a/Kits/DirectXTK12/Src/EffectFactory.cpp +++ b/Kits/DirectXTK12/Src/EffectFactory.cpp @@ -497,11 +497,20 @@ EffectFactory::EffectFactory(_In_ ID3D12DescriptorHeap* textureDescriptors, _In_ throw std::invalid_argument("Descriptor heap cannot be null if no device is provided. Use the alternative EffectFactory constructor instead."); } - if (textureDescriptors->GetDesc().Type != D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) +#if defined(_MSC_VER) || !defined(_WIN32) + const D3D12_DESCRIPTOR_HEAP_TYPE textureHeapType = textureDescriptors->GetDesc().Type; + const D3D12_DESCRIPTOR_HEAP_TYPE samplerHeapType = samplerDescriptors->GetDesc().Type; +#else + D3D12_DESCRIPTOR_HEAP_DESC tmpDesc1, tmpDesc2; + const D3D12_DESCRIPTOR_HEAP_TYPE textureHeapType = textureDescriptors->GetDesc(&tmpDesc1)->Type; + const D3D12_DESCRIPTOR_HEAP_TYPE samplerHeapType = samplerDescriptors->GetDesc(&tmpDesc2)->Type; +#endif + + if (textureHeapType != D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) { throw std::invalid_argument("EffectFactory::CreateEffect requires a CBV_SRV_UAV descriptor heap for textureDescriptors."); } - if (samplerDescriptors->GetDesc().Type != D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) + if (samplerHeapType != D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) { throw std::invalid_argument("EffectFactory::CreateEffect requires a SAMPLER descriptor heap for samplerDescriptors."); } diff --git a/Kits/DirectXTK12/Src/EffectPipelineStateDescription.cpp b/Kits/DirectXTK12/Src/EffectPipelineStateDescription.cpp index 4bebb0e..b645ae4 100644 --- a/Kits/DirectXTK12/Src/EffectPipelineStateDescription.cpp +++ b/Kits/DirectXTK12/Src/EffectPipelineStateDescription.cpp @@ -91,7 +91,13 @@ void EffectPipelineStateDescription::CreatePipelineState( const D3D12_SHADER_BYTECODE& pixelShader, _Outptr_ ID3D12PipelineState** pPipelineState) const { +#if defined(_MSC_VER) || !defined(_WIN32) auto psoDesc = GetDesc(); +#else + D3D12_GRAPHICS_PIPELINE_STATE_DESC tmpPSODesc; + auto& psoDesc = *GetDesc(&tmpPSODesc); +#endif + psoDesc.pRootSignature = rootSignature; psoDesc.VS = vertexShader; psoDesc.PS = pixelShader; diff --git a/Kits/DirectXTK12/Src/GamePad.cpp b/Kits/DirectXTK12/Src/GamePad.cpp index 116f02d..65b43c4 100644 --- a/Kits/DirectXTK12/Src/GamePad.cpp +++ b/Kits/DirectXTK12/Src/GamePad.cpp @@ -1683,11 +1683,7 @@ GamePad& GamePad::Get() // ButtonStateTracker //====================================================================================== -#define UPDATE_BUTTON_STATE(field) field = static_cast( ( !!state.buttons.field ) | ( ( !!state.buttons.field ^ !!lastState.buttons.field ) << 1 ) ); - -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wextra-semi-stmt" -#endif +#define UPDATE_BUTTON_STATE(field) field = static_cast( ( !!state.buttons.field ) | ( ( !!state.buttons.field ^ !!lastState.buttons.field ) << 1 ) ) void GamePad::ButtonStateTracker::Update(const GamePad::State& state) noexcept { diff --git a/Kits/DirectXTK12/Src/LoaderHelpers.h b/Kits/DirectXTK12/Src/LoaderHelpers.h index 6c3298c..cc32708 100644 --- a/Kits/DirectXTK12/Src/LoaderHelpers.h +++ b/Kits/DirectXTK12/Src/LoaderHelpers.h @@ -221,6 +221,37 @@ namespace DirectX } } + //-------------------------------------------------------------------------------------- + inline DXGI_FORMAT MakeLinear(_In_ DXGI_FORMAT format) noexcept + { + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + return DXGI_FORMAT_R8G8B8A8_UNORM; + + case DXGI_FORMAT_BC1_UNORM_SRGB: + return DXGI_FORMAT_BC1_UNORM; + + case DXGI_FORMAT_BC2_UNORM_SRGB: + return DXGI_FORMAT_BC2_UNORM; + + case DXGI_FORMAT_BC3_UNORM_SRGB: + return DXGI_FORMAT_BC3_UNORM; + + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8A8_UNORM; + + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8X8_UNORM; + + case DXGI_FORMAT_BC7_UNORM_SRGB: + return DXGI_FORMAT_BC7_UNORM; + + default: + return format; + } + } + //-------------------------------------------------------------------------------------- inline bool IsCompressed(_In_ DXGI_FORMAT fmt) noexcept { diff --git a/Kits/DirectXTK12/Src/Mouse.cpp b/Kits/DirectXTK12/Src/Mouse.cpp index a782e3f..480ba50 100644 --- a/Kits/DirectXTK12/Src/Mouse.cpp +++ b/Kits/DirectXTK12/Src/Mouse.cpp @@ -1193,8 +1193,8 @@ void Mouse::ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam) if (!pImpl) return; - HANDLE events[3] = { pImpl->mScrollWheelValue.get(), pImpl->mAbsoluteMode.get(), pImpl->mRelativeMode.get() }; - switch (WaitForMultipleObjectsEx(static_cast(std::size(events)), events, FALSE, 0, FALSE)) + // First handle any pending scroll wheel reset event. + switch (WaitForSingleObjectEx(pImpl->mScrollWheelValue.get(), 0, FALSE)) { default: case WAIT_TIMEOUT: @@ -1202,10 +1202,22 @@ void Mouse::ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam) case WAIT_OBJECT_0: pImpl->mState.scrollWheelValue = 0; - ResetEvent(events[0]); + ResetEvent(pImpl->mScrollWheelValue.get()); break; - case (WAIT_OBJECT_0 + 1): + case WAIT_FAILED: + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "WaitForMultipleObjectsEx"); + } + + // Next handle mode change events. + HANDLE events[2] = { pImpl->mAbsoluteMode.get(), pImpl->mRelativeMode.get() }; + switch (WaitForMultipleObjectsEx(static_cast(std::size(events)), events, FALSE, 0, FALSE)) + { + default: + case WAIT_TIMEOUT: + break; + + case WAIT_OBJECT_0: { pImpl->mMode = MODE_ABSOLUTE; ClipCursor(nullptr); @@ -1226,7 +1238,7 @@ void Mouse::ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam) } break; - case (WAIT_OBJECT_0 + 2): + case (WAIT_OBJECT_0 + 1): { ResetEvent(pImpl->mRelativeRead.get()); @@ -1484,11 +1496,7 @@ Mouse& Mouse::Get() // ButtonStateTracker //====================================================================================== -#define UPDATE_BUTTON_STATE(field) field = static_cast( ( !!state.field ) | ( ( !!state.field ^ !!lastState.field ) << 1 ) ); - -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wextra-semi-stmt" -#endif +#define UPDATE_BUTTON_STATE(field) field = static_cast( ( !!state.field ) | ( ( !!state.field ^ !!lastState.field ) << 1 ) ) void Mouse::ButtonStateTracker::Update(const Mouse::State& state) noexcept { diff --git a/Kits/DirectXTK12/Src/PBREffectFactory.cpp b/Kits/DirectXTK12/Src/PBREffectFactory.cpp index 6bcbaec..734a13b 100644 --- a/Kits/DirectXTK12/Src/PBREffectFactory.cpp +++ b/Kits/DirectXTK12/Src/PBREffectFactory.cpp @@ -257,11 +257,20 @@ PBREffectFactory::PBREffectFactory(_In_ ID3D12DescriptorHeap* textureDescriptors throw std::invalid_argument("Descriptor heap cannot be null if no device is provided. Use the alternative PBREffectFactory constructor instead."); } - if (textureDescriptors->GetDesc().Type != D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) +#if defined(_MSC_VER) || !defined(_WIN32) + const D3D12_DESCRIPTOR_HEAP_TYPE textureHeapType = textureDescriptors->GetDesc().Type; + const D3D12_DESCRIPTOR_HEAP_TYPE samplerHeapType = samplerDescriptors->GetDesc().Type; +#else + D3D12_DESCRIPTOR_HEAP_DESC tmpDesc1, tmpDesc2; + const D3D12_DESCRIPTOR_HEAP_TYPE textureHeapType = textureDescriptors->GetDesc(&tmpDesc1)->Type; + const D3D12_DESCRIPTOR_HEAP_TYPE samplerHeapType = samplerDescriptors->GetDesc(&tmpDesc2)->Type; +#endif + + if (textureHeapType != D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) { throw std::invalid_argument("PBREffectFactory::CreateEffect requires a CBV_SRV_UAV descriptor heap for textureDescriptors."); } - if (samplerDescriptors->GetDesc().Type != D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) + if (samplerHeapType != D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) { throw std::invalid_argument("PBREffectFactory::CreateEffect requires a SAMPLER descriptor heap for samplerDescriptors."); } diff --git a/Kits/DirectXTK12/Src/PrimitiveBatch.cpp b/Kits/DirectXTK12/Src/PrimitiveBatch.cpp index 1a5c2b3..1dc1e4e 100644 --- a/Kits/DirectXTK12/Src/PrimitiveBatch.cpp +++ b/Kits/DirectXTK12/Src/PrimitiveBatch.cpp @@ -14,7 +14,7 @@ #include "GraphicsMemory.h" using namespace DirectX; -using namespace DirectX::Internal; +using namespace DirectX::DX12::Private; using Microsoft::WRL::ComPtr; diff --git a/Kits/DirectXTK12/Src/ResourceUploadBatch.cpp b/Kits/DirectXTK12/Src/ResourceUploadBatch.cpp index 6510c0d..d8f22f9 100644 --- a/Kits/DirectXTK12/Src/ResourceUploadBatch.cpp +++ b/Kits/DirectXTK12/Src/ResourceUploadBatch.cpp @@ -418,7 +418,12 @@ public: throw std::runtime_error("GenerateMips cannot operate on a copy queue"); } + #if defined(_MSC_VER) || !defined(_WIN32) const auto desc = resource->GetDesc(); + #else + D3D12_RESOURCE_DESC tmpDesc; + const auto& desc = *resource->GetDesc(&tmpDesc); + #endif if (desc.MipLevels == 1) { @@ -626,7 +631,12 @@ private: void GenerateMips_UnorderedAccessPath( _In_ ID3D12Resource* resource) { + #if defined(_MSC_VER) || !defined(_WIN32) const auto desc = resource->GetDesc(); + #else + D3D12_RESOURCE_DESC tmpDesc; + const auto& desc = *resource->GetDesc(&tmpDesc); + #endif assert(!FormatIsBGR(desc.Format) && !FormatIsSRGB(desc.Format)); const CD3DX12_HEAP_PROPERTIES defaultHeapProperties(D3D12_HEAP_TYPE_DEFAULT); @@ -683,7 +693,12 @@ private: auto const descriptorSize = static_cast(mDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)); // Create the top-level SRV + #if defined(_MSC_VER) || !defined(_WIN32) CD3DX12_CPU_DESCRIPTOR_HANDLE handleIt(descriptorHeap->GetCPUDescriptorHandleForHeapStart()); + #else + CD3DX12_CPU_DESCRIPTOR_HANDLE handleIt; + std::ignore = descriptorHeap->GetCPUDescriptorHandleForHeapStart(&handleIt); + #endif D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; srvDesc.Format = desc.Format; srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; @@ -734,12 +749,17 @@ private: mList->SetComputeRootSignature(mGenMipsResources->rootSignature.Get()); mList->SetPipelineState(pso.Get()); mList->SetDescriptorHeaps(1, descriptorHeap.GetAddressOf()); - mList->SetComputeRootDescriptorTable(GenerateMipsResources::SourceTexture, descriptorHeap->GetGPUDescriptorHandleForHeapStart()); + + #if defined(_MSC_VER) || !defined(_WIN32) + D3D12_GPU_DESCRIPTOR_HANDLE handle(descriptorHeap->GetGPUDescriptorHandleForHeapStart()); + #else + D3D12_GPU_DESCRIPTOR_HANDLE handle; + std::ignore = descriptorHeap->GetGPUDescriptorHandleForHeapStart(&handle); + #endif + mList->SetComputeRootDescriptorTable(GenerateMipsResources::SourceTexture, handle); // Get the descriptor handle -- uavH will increment over each loop - CD3DX12_GPU_DESCRIPTOR_HANDLE uavH( - descriptorHeap->GetGPUDescriptorHandleForHeapStart(), - descriptorSize); // offset by 1 descriptor + CD3DX12_GPU_DESCRIPTOR_HANDLE uavH(handle, descriptorSize); // offset by 1 descriptor // Process each mip auto mipWidth = static_cast(desc.Width); @@ -823,7 +843,12 @@ private: void GenerateMips_TexturePath( _In_ ID3D12Resource* resource) { + #if defined(_MSC_VER) || !defined(_WIN32) const auto resourceDesc = resource->GetDesc(); + #else + D3D12_RESOURCE_DESC tmpDesc; + const auto& resourceDesc = *resource->GetDesc(&tmpDesc); + #endif assert(!FormatIsBGR(resourceDesc.Format) || FormatIsSRGB(resourceDesc.Format)); auto copyDesc = resourceDesc; @@ -888,7 +913,12 @@ private: void GenerateMips_TexturePathBGR( _In_ ID3D12Resource* resource) { + #if defined(_MSC_VER) || !defined(_WIN32) const auto resourceDesc = resource->GetDesc(); + #else + D3D12_RESOURCE_DESC tmpDesc; + const auto& resourceDesc = *resource->GetDesc(&tmpDesc); + #endif assert(FormatIsBGR(resourceDesc.Format)); // Create a resource with the same description with RGB and with UAV flags @@ -900,7 +930,12 @@ private: #endif D3D12_HEAP_DESC heapDesc = {}; + #if defined(_MSC_VER) || !defined(_WIN32) auto const allocInfo = mDevice->GetResourceAllocationInfo(0, 1, ©Desc); + #else + D3D12_RESOURCE_ALLOCATION_INFO allocInfo; + std::ignore = mDevice->GetResourceAllocationInfo(&allocInfo, 0, 1, ©Desc); + #endif heapDesc.SizeInBytes = allocInfo.SizeInBytes; heapDesc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES; heapDesc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT; diff --git a/Kits/DirectXTK12/Src/ScreenGrab.cpp b/Kits/DirectXTK12/Src/ScreenGrab.cpp index f63f120..3ce6f68 100644 --- a/Kits/DirectXTK12/Src/ScreenGrab.cpp +++ b/Kits/DirectXTK12/Src/ScreenGrab.cpp @@ -234,7 +234,12 @@ HRESULT DirectX::SaveDDSTextureToFile( pCommandQ->GetDevice(IID_GRAPHICS_PPV_ARGS(device.GetAddressOf())); // Get the size of the image +#if defined(_MSC_VER) || !defined(_WIN32) const auto desc = pSource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& desc = *pSource->GetDesc(&tmpDesc); +#endif if (desc.Width > UINT32_MAX) return E_INVALIDARG; @@ -430,9 +435,12 @@ HRESULT DirectX::SaveDDSTextureToFile( //-------------------------------------------------------------------------------------- namespace DirectX { - namespace Internal + inline namespace DX12 { - extern IWICImagingFactory2* GetWIC() noexcept; + namespace Internal + { + extern IWICImagingFactory2* GetWIC() noexcept; + } } } @@ -448,7 +456,7 @@ HRESULT DirectX::SaveWICTextureToFile( std::function setCustomProps, bool forceSRGB) { - using namespace DirectX::Internal; + using namespace DirectX::DX12::Internal; if (!fileName) return E_INVALIDARG; @@ -457,7 +465,12 @@ HRESULT DirectX::SaveWICTextureToFile( pCommandQ->GetDevice(IID_GRAPHICS_PPV_ARGS(device.GetAddressOf())); // Get the size of the image +#if defined(_MSC_VER) || !defined(_WIN32) const auto desc = pSource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& desc = *pSource->GetDesc(&tmpDesc); +#endif if (desc.Width > UINT32_MAX) return E_INVALIDARG; diff --git a/Kits/DirectXTK12/Src/Shaders/CompileShaders.cmd b/Kits/DirectXTK12/Src/Shaders/CompileShaders.cmd index b625aed..24c68a4 100644 --- a/Kits/DirectXTK12/Src/Shaders/CompileShaders.cmd +++ b/Kits/DirectXTK12/Src/Shaders/CompileShaders.cmd @@ -46,6 +46,7 @@ if not exist %XBOXDXC% goto needgxdk goto continue :continuedxil +if defined DirectXShaderCompiler goto dxcviaenv set PCDXC="%WindowsSdkVerBinPath%x86\dxc.exe" if exist %PCDXC% goto continue set PCDXC="%WindowsSdkBinPath%%WindowsSDKVersion%\x86\dxc.exe" @@ -54,6 +55,11 @@ if exist %PCDXC% goto continue set PCDXC=dxc.exe goto continue +:dxcviaenv +set PCDXC="%DirectXShaderCompiler%" +if exist %PCDXC% goto continue +goto needdxil + :continuepc set PCOPTS= @@ -284,56 +290,56 @@ endlocal exit /b 0 :CompileShader -set fxc=%PCFXC% %1.fx %FXCOPTS% /T%2_5_1 %PCOPTS% /E%3 "/Fh%CompileShadersOutput%\%1_%3.inc" "/Fd%CompileShadersOutput%\%1_%3.pdb" /Vn%1_%3 +set fxc=%PCFXC% "%1.fx" %FXCOPTS% /T%2_5_1 %PCOPTS% /E%3 "/Fh%CompileShadersOutput%\%1_%3.inc" "/Fd%CompileShadersOutput%\%1_%3.pdb" /Vn%1_%3 echo. echo %fxc% %fxc% || set error=1 exit /b :CompileComputeShader -set fxc=%PCFXC% %1.hlsl %FXCOPTS% /Tcs_5_1 %PCOPTS% /E%2 "/Fh%CompileShadersOutput%\%1_%2.inc" "/Fd%CompileShadersOutput%\%1_%2.pdb" /Vn%1_%2 +set fxc=%PCFXC% "%1.hlsl" %FXCOPTS% /Tcs_5_1 %PCOPTS% /E%2 "/Fh%CompileShadersOutput%\%1_%2.inc" "/Fd%CompileShadersOutput%\%1_%2.pdb" /Vn%1_%2 echo. echo %fxc% %fxc% || set error=1 exit /b :CompileShaderdxil -set dxc=%PCDXC% %1.fx %FXCOPTS% /T%2_6_0 /E%3 "/Fh%CompileShadersOutput%\%1_%3.inc" "/Fd%CompileShadersOutput%\%1_%3.pdb" /Vn%1_%3 +set dxc=%PCDXC% "%1.fx" %FXCOPTS% /T%2_6_0 /E%3 "/Fh%CompileShadersOutput%\%1_%3.inc" "/Fd%CompileShadersOutput%\%1_%3.pdb" /Vn%1_%3 echo. echo %dxc% %dxc% || set error=1 exit /b :CompileComputeShaderdxil -set dxc=%PCDXC% %1.hlsl %FXCOPTS% /Tcs_6_0 /E%2 "/Fh%CompileShadersOutput%\%1_%2.inc" "/Fd%CompileShadersOutput%\%1_%2.pdb" /Vn%1_%2 +set dxc=%PCDXC% "%1.hlsl" %FXCOPTS% /Tcs_6_0 /E%2 "/Fh%CompileShadersOutput%\%1_%2.inc" "/Fd%CompileShadersOutput%\%1_%2.pdb" /Vn%1_%2 echo. echo %dxc% %dxc% || set error=1 exit /b :CompileShaderxbox -set fxc=%XBOXFXC% %1.fx %FXCOPTS% /T%2_5_1 %XBOXOPTS% /E%3 "/Fh%CompileShadersOutput%\%XBOXPREFIX%%1_%3.inc" "/Fd%CompileShadersOutput%\%XBOXPREFIX%%1_%3.pdb" /Vn%1_%3 +set fxc=%XBOXFXC% "%1.fx" %FXCOPTS% /T%2_5_1 %XBOXOPTS% /E%3 "/Fh%CompileShadersOutput%\%XBOXPREFIX%%1_%3.inc" "/Fd%CompileShadersOutput%\%XBOXPREFIX%%1_%3.pdb" /Vn%1_%3 echo. echo %fxc% %fxc% || set error=1 exit /b :CompileComputeShaderxbox -set fxc==%XBOXFXC% %1.hlsl %FXCOPTS% /Tcs_5_1 %XBOXOPTS% /E%2 "/Fh%CompileShadersOutput%\%XBOXPREFIX%%1_%2.inc" "/Fd%CompileShadersOutput%\%XBOXPREFIX%%1_%2.pdb" /Vn%1_%2 +set fxc==%XBOXFXC% "%1.hlsl" %FXCOPTS% /Tcs_5_1 %XBOXOPTS% /E%2 "/Fh%CompileShadersOutput%\%XBOXPREFIX%%1_%2.inc" "/Fd%CompileShadersOutput%\%XBOXPREFIX%%1_%2.pdb" /Vn%1_%2 echo. echo %fxc% %fxc% || set error=1 exit /b :CompileShadergxdk -set dxc=%XBOXDXC% %1.fx %FXCOPTS% /T%2_6_0 /E%3 "/Fh%CompileShadersOutput%\%XBOXPREFIX%%1_%3.inc" "/Fd%CompileShadersOutput%\%XBOXPREFIX%%1_%3.pdb" /Vn%1_%3 +set dxc=%XBOXDXC% "%1.fx" %FXCOPTS% /T%2_6_0 /E%3 "/Fh%CompileShadersOutput%\%XBOXPREFIX%%1_%3.inc" "/Fd%CompileShadersOutput%\%XBOXPREFIX%%1_%3.pdb" /Vn%1_%3 echo. echo %dxc% %dxc% || set error=1 exit /b :CompileComputeShadergxdk -set dxc=%XBOXDXC% %1.hlsl %FXCOPTS% /Tcs_6_0 /E%2 "/Fh%CompileShadersOutput%\%XBOXPREFIX%%1_%2.inc" "/Fd%CompileShadersOutput%\%XBOXPREFIX%%1_%2.pdb" /Vn%1_%2 +set dxc=%XBOXDXC% "%1.hlsl" %FXCOPTS% /Tcs_6_0 /E%2 "/Fh%CompileShadersOutput%\%XBOXPREFIX%%1_%2.inc" "/Fd%CompileShadersOutput%\%XBOXPREFIX%%1_%2.pdb" /Vn%1_%2 echo. echo %dxc% %dxc% || set error=1 @@ -342,9 +348,13 @@ exit /b :needxdk echo ERROR: CompileShaders xbox requires the Microsoft Xbox One XDK echo (try re-running from the XDK Command Prompt) -exit /b +exit /b 1 :needgxdk echo ERROR: CompileShaders gxdk requires the Microsoft Gaming SDK -echo (try re-running from the Gaming GXDK Command Prompt) -exit /b +echo (try re-running from the Microsoft GDKX Gaming Command Prompt) +exit /b 1 + +:needdxil +echo ERROR: CompileShaders dxil requires DXC.EXE +exit /b 1 diff --git a/Kits/DirectXTK12/Src/WICTextureLoader.cpp b/Kits/DirectXTK12/Src/WICTextureLoader.cpp index 6bff4b6..fe0ffda 100644 --- a/Kits/DirectXTK12/Src/WICTextureLoader.cpp +++ b/Kits/DirectXTK12/Src/WICTextureLoader.cpp @@ -154,14 +154,17 @@ namespace //-------------------------------------------------------------------------------------- namespace DirectX { - namespace Internal + inline namespace DX12 { - IWICImagingFactory2* GetWIC() noexcept; - // Also used by ScreenGrab + namespace Internal + { + IWICImagingFactory2* GetWIC() noexcept; + // Also used by ScreenGrab + } } } -IWICImagingFactory2* DirectX::Internal::GetWIC() noexcept +IWICImagingFactory2* DirectX::DX12::Internal::GetWIC() noexcept { static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT; @@ -178,7 +181,7 @@ IWICImagingFactory2* DirectX::Internal::GetWIC() noexcept return factory; } -using namespace Internal; +using namespace DirectX::DX12::Internal; namespace { diff --git a/Kits/DirectXTK12/Src/d3dx12.h b/Kits/DirectXTK12/Src/d3dx12.h index 42f26a6..e873d96 100644 --- a/Kits/DirectXTK12/Src/d3dx12.h +++ b/Kits/DirectXTK12/Src/d3dx12.h @@ -76,7 +76,12 @@ struct CD3DX12_VIEWPORT : public D3D12_VIEWPORT FLOAT minDepth = D3D12_MIN_DEPTH, FLOAT maxDepth = D3D12_MAX_DEPTH ) noexcept { +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pResource->GetDesc(&tmpDesc); +#endif const UINT64 SubresourceWidth = Desc.Width >> mipSlice; const UINT64 SubresourceHeight = Desc.Height >> mipSlice; switch (Desc.Dimension) @@ -2040,7 +2045,12 @@ inline UINT64 GetRequiredIntermediateSize( _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources) noexcept { +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif UINT64 RequiredSize = 0; ID3D12Device* pDevice = nullptr; @@ -2066,8 +2076,14 @@ inline UINT64 UpdateSubresources( _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept { // Minor validation +#if defined(_MSC_VER) || !defined(_WIN32) const auto IntermediateDesc = pIntermediate->GetDesc(); const auto DestinationDesc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc1, tmpDesc2; + const auto& IntermediateDesc = *pIntermediate->GetDesc(&tmpDesc1); + const auto& DestinationDesc = *pDestinationResource->GetDesc(&tmpDesc2); +#endif if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || RequiredSize > SIZE_T(-1) || @@ -2125,8 +2141,14 @@ inline UINT64 UpdateSubresources( _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_INFO* pSrcData) noexcept { // Minor validation +#if defined(_MSC_VER) || !defined(_WIN32) const auto IntermediateDesc = pIntermediate->GetDesc(); const auto DestinationDesc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc1, tmpDesc2; + const auto& IntermediateDesc = *pIntermediate->GetDesc(&tmpDesc1); + const auto& DestinationDesc = *pDestinationResource->GetDesc(&tmpDesc2); +#endif if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || RequiredSize > SIZE_T(-1) || @@ -2194,7 +2216,12 @@ inline UINT64 UpdateSubresources( auto pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); auto pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif ID3D12Device* pDevice = nullptr; pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast(&pDevice)); pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); @@ -2232,7 +2259,12 @@ inline UINT64 UpdateSubresources( auto pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); auto pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif ID3D12Device* pDevice = nullptr; pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast(&pDevice)); pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); @@ -2260,7 +2292,12 @@ inline UINT64 UpdateSubresources( UINT NumRows[MaxSubresources]; UINT64 RowSizesInBytes[MaxSubresources]; +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif ID3D12Device* pDevice = nullptr; pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast(&pDevice)); pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize); @@ -2287,7 +2324,12 @@ inline UINT64 UpdateSubresources( UINT NumRows[MaxSubresources]; UINT64 RowSizesInBytes[MaxSubresources]; +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif ID3D12Device* pDevice = nullptr; pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast(&pDevice)); pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize); @@ -4071,20 +4113,20 @@ public: D3D12_BARRIER_SUBRESOURCE_RANGE{ Subresource, 0, 0, 0, 0, 0 } {} CD3DX12_BARRIER_SUBRESOURCE_RANGE( - UINT FirstMipLevel, - UINT NumMips, - UINT FirstArraySlice, - UINT NumArraySlices, - UINT FirstPlane = 0, - UINT NumPlanes = 1) noexcept : + UINT firstMipLevel, + UINT numMips, + UINT firstArraySlice, + UINT numArraySlices, + UINT firstPlane = 0, + UINT numPlanes = 1) noexcept : D3D12_BARRIER_SUBRESOURCE_RANGE { - FirstMipLevel, - NumMips, - FirstArraySlice, - NumArraySlices, - FirstPlane, - NumPlanes + firstMipLevel, + numMips, + firstArraySlice, + numArraySlices, + firstPlane, + numPlanes } {} }; diff --git a/Kits/DirectXTK12/Src/pch.h b/Kits/DirectXTK12/Src/pch.h index a43a70a..e82b091 100644 --- a/Kits/DirectXTK12/Src/pch.h +++ b/Kits/DirectXTK12/Src/pch.h @@ -10,7 +10,7 @@ #pragma once // Off by default warnings -#pragma warning(disable : 4619 4061 4265 4355 4365 4571 4623 4625 4626 4628 4668 4710 4711 4746 4774 4820 4987 5026 5027 5031 5032 5039 5045 5219 5246 26812) +#pragma warning(disable : 4619 4061 4265 4355 4365 4571 4623 4625 4626 4628 4668 4710 4711 4746 4774 4820 4987 5026 5027 5031 5032 5039 5045 5219 5246 5264 26812) // C4619 #pragma warning: there is no warning number 'X' // C4061 enumerator 'X' in switch of enum 'X' is not explicitly handled by a case label // C4265 class has virtual functions, but destructor is not virtual @@ -35,6 +35,7 @@ // C5045 Spectre mitigation warning // C5219 implicit conversion from 'int' to 'float', possible loss of data // C5246 the initialization of a subobject should be wrapped in braces +// C5264 'const' variable is not used // 26812: The enum type 'x' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). // XBox One XDK related Off by default warnings @@ -234,6 +235,12 @@ #include +#if defined(NTDDI_WIN10_FE) || defined(__MINGW32__) +#include +#else +#include +#endif + #ifndef __MINGW32__ // DirectX Tool Kit for Audio is in all versions of DirectXTK12 #include diff --git a/Kits/DirectXTex/BC.h b/Kits/DirectXTex/BC.h index 44482b4..cef5404 100644 --- a/Kits/DirectXTex/BC.h +++ b/Kits/DirectXTex/BC.h @@ -60,7 +60,6 @@ namespace DirectX public: HDRColorA() = default; HDRColorA(float _r, float _g, float _b, float _a) noexcept : r(_r), g(_g), b(_b), a(_a) {} - HDRColorA(const HDRColorA& c) noexcept : r(c.r), g(c.g), b(c.b), a(c.a) {} // binary operators HDRColorA operator + (const HDRColorA& c) const noexcept diff --git a/Kits/DirectXTex/BC6HBC7.cpp b/Kits/DirectXTex/BC6HBC7.cpp index 2a889d8..132f86e 100644 --- a/Kits/DirectXTex/BC6HBC7.cpp +++ b/Kits/DirectXTex/BC6HBC7.cpp @@ -452,7 +452,6 @@ namespace public: INTColor() = default; INTColor(int nr, int ng, int nb) noexcept : r(nr), g(ng), b(nb), pad(0) {} - INTColor(const INTColor& c) noexcept : r(c.r), g(c.g), b(c.b), pad(0) {} INTColor& operator += (_In_ const INTColor& c) noexcept { @@ -751,9 +750,12 @@ namespace float RoughMSE(_Inout_ EncodeParams* pEP) const noexcept; private: - static const ModeDescriptor ms_aDesc[][82]; - static const ModeInfo ms_aInfo[]; - static const int ms_aModeToInfo[]; + static constexpr uint8_t c_NumModes = 14; + static constexpr uint8_t c_NumModeInfo = 32; + + static const ModeDescriptor ms_aDesc[c_NumModes][82]; + static const ModeInfo ms_aInfo[c_NumModes]; + static const int ms_aModeToInfo[c_NumModeInfo]; }; // BC67 compression (16b bits per texel) @@ -856,12 +858,14 @@ namespace static float RoughMSE(_Inout_ EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uIndexMode) noexcept; private: - static const ModeInfo ms_aInfo[]; + static constexpr uint8_t c_NumModes = 8; + + static const ModeInfo ms_aInfo[c_NumModes]; }; } // BC6H Compression -const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] = +const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[D3DX_BC6H::c_NumModes][82] = { { // Mode 1 (0x00) - 10 5 5 5 { M, 0}, { M, 1}, {GY, 4}, {BY, 4}, {BZ, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, @@ -1033,7 +1037,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] = }; // Mode, Partitions, Transformed, IndexPrec, RGBAPrec -const D3DX_BC6H::ModeInfo D3DX_BC6H::ms_aInfo[] = +const D3DX_BC6H::ModeInfo D3DX_BC6H::ms_aInfo[D3DX_BC6H::c_NumModes] = { {0x00, 1, true, 3, { { LDRColorA(10,10,10,0), LDRColorA(5, 5, 5,0) }, { LDRColorA(5,5,5,0), LDRColorA(5,5,5,0) } } }, // Mode 1 {0x01, 1, true, 3, { { LDRColorA(7, 7, 7,0), LDRColorA(6, 6, 6,0) }, { LDRColorA(6,6,6,0), LDRColorA(6,6,6,0) } } }, // Mode 2 @@ -1051,7 +1055,7 @@ const D3DX_BC6H::ModeInfo D3DX_BC6H::ms_aInfo[] = {0x0f, 0, true, 4, { { LDRColorA(16,16,16,0), LDRColorA(4, 4, 4,0) }, { LDRColorA(0,0,0,0), LDRColorA(0,0,0,0) } } }, // Mode 14 }; -const int D3DX_BC6H::ms_aModeToInfo[] = +const int D3DX_BC6H::ms_aModeToInfo[D3DX_BC6H::c_NumModeInfo] = { 0, // Mode 1 - 0x00 1, // Mode 2 - 0x01 @@ -1088,7 +1092,7 @@ const int D3DX_BC6H::ms_aModeToInfo[] = }; // BC7 compression: uPartitions, uPartitionBits, uPBits, uRotationBits, uIndexModeBits, uIndexPrec, uIndexPrec2, RGBAPrec, RGBAPrecWithP -const D3DX_BC7::ModeInfo D3DX_BC7::ms_aInfo[] = +const D3DX_BC7::ModeInfo D3DX_BC7::ms_aInfo[D3DX_BC7::c_NumModes] = { {2, 4, 6, 0, 0, 3, 0, LDRColorA(4,4,4,0), LDRColorA(5,5,5,0)}, // Mode 0: Color only, 3 Subsets, RGBP 4441 (unique P-bit), 3-bit indecies, 16 partitions @@ -1655,17 +1659,14 @@ void D3DX_BC6H::Decode(bool bSigned, HDRColorA* pOut) const noexcept uMode = static_cast((unsigned(GetBits(uStartBit, 3)) << 2) | uMode); } - assert(uMode < 32); - _Analysis_assume_(uMode < 32); + assert(uMode < c_NumModeInfo); + _Analysis_assume_(uMode < c_NumModeInfo); if (ms_aModeToInfo[uMode] >= 0) { - assert(static_cast(ms_aModeToInfo[uMode]) < std::size(ms_aInfo)); - _Analysis_assume_(ms_aModeToInfo[uMode] < std::size(ms_aInfo)); + assert(static_cast(ms_aModeToInfo[uMode]) < c_NumModes); + _Analysis_assume_(ms_aModeToInfo[uMode] < c_NumModes); const ModeDescriptor* desc = ms_aDesc[ms_aModeToInfo[uMode]]; - - assert(static_cast(ms_aModeToInfo[uMode]) < std::size(ms_aDesc)); - _Analysis_assume_(ms_aModeToInfo[uMode] < std::size(ms_aDesc)); const ModeInfo& info = ms_aInfo[ms_aModeToInfo[uMode]]; INTEndPntPair aEndPts[BC6H_MAX_REGIONS] = {}; @@ -1811,7 +1812,7 @@ void D3DX_BC6H::Encode(bool bSigned, const HDRColorA* const pIn) noexcept EncodeParams EP(pIn, bSigned); - for (EP.uMode = 0; EP.uMode < std::size(ms_aInfo) && EP.fBestErr > 0; ++EP.uMode) + for (EP.uMode = 0; EP.uMode < c_NumModes && EP.fBestErr > 0; ++EP.uMode) { const uint8_t uShapes = ms_aInfo[EP.uMode].uPartitions ? 32u : 1u; // Number of rough cases to look at. reasonable values of this are 1, uShapes/4, and uShapes @@ -1936,6 +1937,9 @@ _Use_decl_annotations_ bool D3DX_BC6H::EndPointsFit(const EncodeParams* pEP, const INTEndPntPair aEndPts[]) noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const bool bTransformed = ms_aInfo[pEP->uMode].bTransformed; const bool bIsSigned = pEP->bSigned; const LDRColorA& Prec0 = ms_aInfo[pEP->uMode].RGBAPrec[0][0]; @@ -1978,6 +1982,9 @@ _Use_decl_annotations_ void D3DX_BC6H::GeneratePaletteQuantized(const EncodeParams* pEP, const INTEndPntPair& endPts, INTColor aPalette[]) const noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const size_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; const size_t uNumIndices = size_t(1) << uIndexPrec; assert(uNumIndices > 0); @@ -2029,6 +2036,8 @@ _Use_decl_annotations_ float D3DX_BC6H::MapColorsQuantized(const EncodeParams* pEP, const INTColor aColors[], size_t np, const INTEndPntPair &endPts) const noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; auto const uNumIndices = static_cast(1u << uIndexPrec); @@ -2065,6 +2074,9 @@ float D3DX_BC6H::PerturbOne(const EncodeParams* pEP, const INTColor aColors[], s const INTEndPntPair& oldEndPts, INTEndPntPair& newEndPts, float fOldErr, int do_b) const noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + uint8_t uPrec; switch (ch) { @@ -2178,6 +2190,9 @@ _Use_decl_annotations_ void D3DX_BC6H::OptimizeEndPoints(const EncodeParams* pEP, const float aOrgErr[], const INTEndPntPair aOrgEndPts[], INTEndPntPair aOptEndPts[]) const noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; assert(uPartitions < BC6H_MAX_REGIONS); _Analysis_assume_(uPartitions < BC6H_MAX_REGIONS); @@ -2205,6 +2220,9 @@ _Use_decl_annotations_ void D3DX_BC6H::SwapIndices(const EncodeParams* pEP, INTEndPntPair aEndPts[], size_t aIndices[]) noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const size_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; const size_t uNumIndices = size_t(1) << ms_aInfo[pEP->uMode].uIndexPrec; const size_t uHighIndexBit = uNumIndices >> 1; @@ -2234,6 +2252,9 @@ _Use_decl_annotations_ void D3DX_BC6H::AssignIndices(const EncodeParams* pEP, const INTEndPntPair aEndPts[], size_t aIndices[], float aTotErr[]) const noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; auto const uNumIndices = static_cast(1u << ms_aInfo[pEP->uMode].uIndexPrec); @@ -2276,6 +2297,9 @@ _Use_decl_annotations_ void D3DX_BC6H::QuantizeEndPts(const EncodeParams* pEP, INTEndPntPair* aQntEndPts) const noexcept { assert(pEP && aQntEndPts); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const INTEndPntPair* aUnqEndPts = pEP->aUnqEndPts[pEP->uShape]; const LDRColorA& Prec = ms_aInfo[pEP->uMode].RGBAPrec[0][0]; const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; @@ -2298,6 +2322,9 @@ _Use_decl_annotations_ void D3DX_BC6H::EmitBlock(const EncodeParams* pEP, const INTEndPntPair aEndPts[], const size_t aIndices[]) noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const uint8_t uRealMode = ms_aInfo[pEP->uMode].uMode; const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; @@ -2342,6 +2369,9 @@ _Use_decl_annotations_ void D3DX_BC6H::Refine(EncodeParams* pEP) noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; assert(uPartitions < BC6H_MAX_REGIONS); _Analysis_assume_(uPartitions < BC6H_MAX_REGIONS); @@ -2394,6 +2424,9 @@ void D3DX_BC6H::GeneratePaletteUnquantized(const EncodeParams* pEP, size_t uRegi assert(pEP); assert(uRegion < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES); _Analysis_assume_(uRegion < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const INTEndPntPair& endPts = pEP->aUnqEndPts[pEP->uShape][uRegion]; const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; auto const uNumIndices = static_cast(1u << uIndexPrec); @@ -2428,6 +2461,9 @@ _Use_decl_annotations_ float D3DX_BC6H::MapColors(const EncodeParams* pEP, size_t uRegion, size_t np, const size_t* auIndex) const noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; auto const uNumIndices = static_cast(1u << uIndexPrec); INTColor aPalette[BC6H_MAX_INDICES]; @@ -2455,6 +2491,8 @@ float D3DX_BC6H::RoughMSE(EncodeParams* pEP) const noexcept assert(pEP); assert(pEP->uShape < BC6H_MAX_SHAPES); _Analysis_assume_(pEP->uShape < BC6H_MAX_SHAPES); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); INTEndPntPair* aEndPts = pEP->aUnqEndPts[pEP->uShape]; @@ -2838,6 +2876,9 @@ _Use_decl_annotations_ void D3DX_BC7::GeneratePaletteQuantized(const EncodeParams* pEP, size_t uIndexMode, const LDREndPntPair& endPts, LDRColorA aPalette[]) const noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const size_t uIndexPrec = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec2 : ms_aInfo[pEP->uMode].uIndexPrec; const size_t uIndexPrec2 = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec : ms_aInfo[pEP->uMode].uIndexPrec2; const size_t uNumIndices = size_t(1) << uIndexPrec; @@ -2868,6 +2909,9 @@ float D3DX_BC7::PerturbOne(const EncodeParams* pEP, const LDRColorA aColors[], s const LDREndPntPair &oldEndPts, LDREndPntPair &newEndPts, float fOldErr, uint8_t do_b) const noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const int prec = ms_aInfo[pEP->uMode].RGBAPrecWithP[ch]; LDREndPntPair tmp_endPts = newEndPts = oldEndPts; float fMinErr = fOldErr; @@ -2910,6 +2954,9 @@ void D3DX_BC7::Exhaustive(const EncodeParams* pEP, const LDRColorA aColors[], si float& fOrgErr, LDREndPntPair& optEndPt) const noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const uint8_t uPrec = ms_aInfo[pEP->uMode].RGBAPrecWithP[ch]; LDREndPntPair tmpEndPt; if (fOrgErr == 0) @@ -2981,6 +3028,8 @@ void D3DX_BC7::OptimizeOne(const EncodeParams* pEP, const LDRColorA aColors[], s float fOrgErr, const LDREndPntPair& org, LDREndPntPair& opt) const noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); float fOptErr = fOrgErr; opt = org; @@ -3047,6 +3096,9 @@ void D3DX_BC7::OptimizeEndPoints(const EncodeParams* pEP, size_t uShape, size_t const LDREndPntPair aOrgEndPts[], LDREndPntPair aOptEndPts[]) const noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; assert(uPartitions < BC7_MAX_REGIONS && uShape < BC7_MAX_SHAPES); _Analysis_assume_(uPartitions < BC7_MAX_REGIONS && uShape < BC7_MAX_SHAPES); @@ -3072,6 +3124,8 @@ void D3DX_BC7::AssignIndices(const EncodeParams* pEP, size_t uShape, size_t uInd assert(pEP); assert(uShape < BC7_MAX_SHAPES); _Analysis_assume_(uShape < BC7_MAX_SHAPES); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; assert(uPartitions < BC7_MAX_REGIONS); @@ -3149,6 +3203,9 @@ _Use_decl_annotations_ void D3DX_BC7::EmitBlock(const EncodeParams* pEP, size_t uShape, size_t uRotation, size_t uIndexMode, const LDREndPntPair aEndPts[], const size_t aIndex[], const size_t aIndex2[]) noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; assert(uPartitions < BC7_MAX_REGIONS); _Analysis_assume_(uPartitions < BC7_MAX_REGIONS); @@ -3236,6 +3293,9 @@ _Use_decl_annotations_ void D3DX_BC7::FixEndpointPBits(const EncodeParams* pEP, const LDREndPntPair *pOrigEndpoints, LDREndPntPair *pFixedEndpoints) noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const size_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; assert(uPartitions < BC7_MAX_REGIONS); _Analysis_assume_(uPartitions < BC7_MAX_REGIONS); @@ -3323,6 +3383,8 @@ float D3DX_BC7::Refine(const EncodeParams* pEP, size_t uShape, size_t uRotation, assert(pEP); assert(uShape < BC7_MAX_SHAPES); _Analysis_assume_(uShape < BC7_MAX_SHAPES); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); const size_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; assert(uPartitions < BC7_MAX_REGIONS); @@ -3379,6 +3441,9 @@ _Use_decl_annotations_ float D3DX_BC7::MapColors(const EncodeParams* pEP, const LDRColorA aColors[], size_t np, size_t uIndexMode, const LDREndPntPair& endPts, float fMinErr) const noexcept { assert(pEP); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + const uint8_t uIndexPrec = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec2 : ms_aInfo[pEP->uMode].uIndexPrec; const uint8_t uIndexPrec2 = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec : ms_aInfo[pEP->uMode].uIndexPrec2; LDRColorA aPalette[BC7_MAX_INDICES]; @@ -3404,6 +3469,9 @@ float D3DX_BC7::RoughMSE(EncodeParams* pEP, size_t uShape, size_t uIndexMode) no assert(pEP); assert(uShape < BC7_MAX_SHAPES); _Analysis_assume_(uShape < BC7_MAX_SHAPES); + assert(pEP->uMode < c_NumModes); + _Analysis_assume_(pEP->uMode < c_NumModes); + LDREndPntPair* aEndPts = pEP->aEndPts[uShape]; const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; diff --git a/Kits/DirectXTex/DirectXTex.h b/Kits/DirectXTex/DirectXTex.h index ba04068..6ab0a45 100644 --- a/Kits/DirectXTex/DirectXTex.h +++ b/Kits/DirectXTex/DirectXTex.h @@ -124,6 +124,7 @@ namespace DirectX size_t __cdecl ComputeScanlines(_In_ DXGI_FORMAT fmt, _In_ size_t height) noexcept; DXGI_FORMAT __cdecl MakeSRGB(_In_ DXGI_FORMAT fmt) noexcept; + DXGI_FORMAT __cdecl MakeLinear(_In_ DXGI_FORMAT fmt) noexcept; DXGI_FORMAT __cdecl MakeTypeless(_In_ DXGI_FORMAT fmt) noexcept; DXGI_FORMAT __cdecl MakeTypelessUNORM(_In_ DXGI_FORMAT fmt) noexcept; DXGI_FORMAT __cdecl MakeTypelessFLOAT(_In_ DXGI_FORMAT fmt) noexcept; @@ -856,6 +857,15 @@ namespace DirectX _Out_ size_t& required) noexcept; //--------------------------------------------------------------------------------- + // Direct3D interop + + enum CREATETEX_FLAGS : uint32_t + { + CREATETEX_DEFAULT = 0, + CREATETEX_FORCE_SRGB = 0x1, + CREATETEX_IGNORE_SRGB = 0x2, + }; + // Direct3D 11 functions #if defined(__d3d11_h__) || defined(__d3d11_x_h__) bool __cdecl IsSupportedTexture(_In_ ID3D11Device* pDevice, _In_ const TexMetadata& metadata) noexcept; @@ -870,18 +880,17 @@ namespace DirectX HRESULT __cdecl CreateTextureEx( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, - _In_ D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB, + _In_ D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ CREATETEX_FLAGS flags, _Outptr_ ID3D11Resource** ppResource) noexcept; HRESULT __cdecl CreateShaderResourceViewEx( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, - _In_ D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB, + _In_ D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ CREATETEX_FLAGS flags, _Outptr_ ID3D11ShaderResourceView** ppSRV) noexcept; HRESULT __cdecl CaptureTexture(_In_ ID3D11Device* pDevice, _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource* pSource, _Out_ ScratchImage& result) noexcept; #endif - //--------------------------------------------------------------------------------- // Direct3D 12 functions #if defined(__d3d12_h__) || defined(__d3d12_x_h__) || defined(__XBOX_D3D12_X__) bool __cdecl IsSupportedTexture(_In_ ID3D12Device* pDevice, _In_ const TexMetadata& metadata) noexcept; @@ -892,7 +901,7 @@ namespace DirectX HRESULT __cdecl CreateTextureEx( _In_ ID3D12Device* pDevice, _In_ const TexMetadata& metadata, - _In_ D3D12_RESOURCE_FLAGS resFlags, _In_ bool forceSRGB, + _In_ D3D12_RESOURCE_FLAGS resFlags, _In_ CREATETEX_FLAGS flags, _Outptr_ ID3D12Resource** ppResource) noexcept; HRESULT __cdecl PrepareUpload( diff --git a/Kits/DirectXTex/DirectXTex.inl b/Kits/DirectXTex/DirectXTex.inl index 1ca81f9..7fef321 100644 --- a/Kits/DirectXTex/DirectXTex.inl +++ b/Kits/DirectXTex/DirectXTex.inl @@ -24,6 +24,7 @@ DEFINE_ENUM_FLAG_OPERATORS(TEX_PMALPHA_FLAGS); DEFINE_ENUM_FLAG_OPERATORS(TEX_COMPRESS_FLAGS); DEFINE_ENUM_FLAG_OPERATORS(CNMAP_FLAGS); DEFINE_ENUM_FLAG_OPERATORS(CMSE_FLAGS); +DEFINE_ENUM_FLAG_OPERATORS(CREATETEX_FLAGS); // WIC_FILTER modes match TEX_FILTER modes constexpr WIC_FLAGS operator|(WIC_FLAGS a, TEX_FILTER_FLAGS b) { return static_cast(static_cast(a) | static_cast(b & TEX_FILTER_MODE_MASK)); } diff --git a/Kits/DirectXTex/DirectXTexP.h b/Kits/DirectXTex/DirectXTexP.h index 7a55e0d..38fdc44 100644 --- a/Kits/DirectXTex/DirectXTexP.h +++ b/Kits/DirectXTex/DirectXTexP.h @@ -12,7 +12,7 @@ #pragma once // Off by default warnings -#pragma warning(disable : 4619 4616 4061 4265 4365 4571 4623 4625 4626 4628 4668 4710 4711 4746 4774 4820 4987 5026 5027 5031 5032 5039 5045 5219 5246 26812) +#pragma warning(disable : 4619 4616 4061 4265 4365 4571 4623 4625 4626 4628 4668 4710 4711 4746 4774 4820 4987 5026 5027 5031 5032 5039 5045 5219 5246 5264 26812) // C4619/4616 #pragma warning warnings // C4061 enumerator 'X' in switch of enum 'X' is not explicitly handled by a case label // C4265 class has virtual functions, but destructor is not virtual @@ -36,6 +36,7 @@ // C5045 Spectre mitigation warning // C5219 implicit conversion from 'int' to 'float', possible loss of data // C5246 the initialization of a subobject should be wrapped in braces +// C5264 'const' variable is not used // 26812: The enum type 'x' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). // Windows 8.1 SDK related Off by default warnings @@ -153,9 +154,9 @@ #include "DirectXTex.h" +#ifdef _WIN32 #include -#ifdef _WIN32 #if defined(NTDDI_WIN10_FE) || defined(__MINGW32__) #include #else diff --git a/Kits/DirectXTex/DirectXTexUtil.cpp b/Kits/DirectXTex/DirectXTexUtil.cpp index 02a00fd..ea24728 100644 --- a/Kits/DirectXTex/DirectXTexUtil.cpp +++ b/Kits/DirectXTex/DirectXTexUtil.cpp @@ -1183,6 +1183,41 @@ DXGI_FORMAT DirectX::MakeSRGB(DXGI_FORMAT fmt) noexcept } +//------------------------------------------------------------------------------------- +// Converts to an non-SRGB equivalent type +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +DXGI_FORMAT DirectX::MakeLinear(DXGI_FORMAT fmt) noexcept +{ + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + return DXGI_FORMAT_R8G8B8A8_UNORM; + + case DXGI_FORMAT_BC1_UNORM_SRGB: + return DXGI_FORMAT_BC1_UNORM; + + case DXGI_FORMAT_BC2_UNORM_SRGB: + return DXGI_FORMAT_BC2_UNORM; + + case DXGI_FORMAT_BC3_UNORM_SRGB: + return DXGI_FORMAT_BC3_UNORM; + + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8A8_UNORM; + + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8X8_UNORM; + + case DXGI_FORMAT_BC7_UNORM_SRGB: + return DXGI_FORMAT_BC7_UNORM; + + default: + return fmt; + } +} + + //------------------------------------------------------------------------------------- // Converts to a format to an equivalent TYPELESS format if available //------------------------------------------------------------------------------------- diff --git a/Kits/DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj b/Kits/DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj index fab1fa2..e3987fc 100644 --- a/Kits/DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj +++ b/Kits/DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj @@ -169,6 +169,7 @@ true /Zc:twoPhase- /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) Level4 + true true @@ -196,6 +197,7 @@ true /Zc:twoPhase- /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) Level4 + true true diff --git a/Kits/DirectXTex/README.md b/Kits/DirectXTex/README.md index 76349ba..750cf31 100644 --- a/Kits/DirectXTex/README.md +++ b/Kits/DirectXTex/README.md @@ -6,11 +6,11 @@ http://go.microsoft.com/fwlink/?LinkId=248926 Copyright (c) Microsoft Corporation. -**May 9, 2022** +**October 17, 2022** This package contains DirectXTex, a shared source library for reading and writing ``.DDS`` files, and performing various texture content processing operations including resizing, format conversion, mip-map generation, block compression for Direct3D runtime texture resources, and height-map to normal-map conversion. This library makes use of the Windows Image Component (WIC) APIs. It also includes ``.TGA`` and ``.HDR`` readers and writers since these image file formats are commonly used for texture content processing pipelines, but are not currently supported by a built-in WIC codec. -This code is designed to build with Visual Studio 2019 (16.9 or later), Visual Studio 2022, or clang for Windows v11 or later. Use of the Windows 10 May 2020 Update SDK ([19041](https://walbourn.github.io/windows-10-may-2020-update-sdk/)) or later is required. +This code is designed to build with Visual Studio 2019 (16.11), Visual Studio 2022, or clang for Windows v11 or later. Use of the Windows 10 May 2020 Update SDK ([19041](https://walbourn.github.io/windows-10-may-2020-update-sdk/)) or later is required. These components are designed to work without requiring any content from the legacy DirectX SDK. For details, see [Where is the DirectX SDK?](https://aka.ms/dxsdk). @@ -71,6 +71,8 @@ For the latest version of DirectXTex, bug reports, etc. please visit the project ## Release Notes +* Starting with the July 2022 release, the ``bool forceSRGB`` parameter for the CreateTextureEx and CreateShaderResourceViewEx functions is now a ``CREATETEX_FLAGS`` typed enum bitmask flag parameter. This may have a *breaking change* impact to client code. Replace ``true`` with ``CREATETEX_FORCE_SRGB`` and ``false`` with ``CREATETEX_DEFAULT``. + * Starting with the June 2020 release, this library makes use of typed enum bitmask flags per the recommendation of the _C++ Standard_ section *17.5.2.1.3 Bitmask types*. This is consistent with Direct3D 12's use of the ``DEFINE_ENUM_FLAG_OPERATORS`` macro. This may have *breaking change* impacts to client code: * You cannot pass the ``0`` literal as your flags value. Instead you must make use of the appropriate default enum value: ``CP_FLAGS_NONE``, ``DDS_FLAGS_NONE``, ``WIC_FLAGS_NONE``, ``TEX_FR_ROTATE0``, ``TEX_FILTER_DEFAULT``, ``TEX_FILTER_DEFAULT``, ``TEX_FILTER_DEFAULT``, ``CNMAP_DEFAULT``, or ``CNMAP_DEFAULT``. diff --git a/Kits/DirectXTex/Shaders/CompileShaders.cmd b/Kits/DirectXTex/Shaders/CompileShaders.cmd index 6d953bb..13418e0 100644 --- a/Kits/DirectXTex/Shaders/CompileShaders.cmd +++ b/Kits/DirectXTex/Shaders/CompileShaders.cmd @@ -44,7 +44,7 @@ endlocal exit /b 0 :CompileShader -set fxc=%PCFXC% %1.hlsl %FXCOPTS% /Tcs_4_0 /E%2 "/Fh%CompileShadersOutput%\%1_%2.inc" "/Fd%CompileShadersOutput%\%1_%2.pdb" /Vn%1_%2 +set fxc=%PCFXC% "%1.hlsl" %FXCOPTS% /Tcs_4_0 /E%2 "/Fh%CompileShadersOutput%\%1_%2.inc" "/Fd%CompileShadersOutput%\%1_%2.pdb" /Vn%1_%2 echo. echo %fxc% %fxc% || set error=1 diff --git a/Kits/DirectXTex/d3dx12.h b/Kits/DirectXTex/d3dx12.h index 42f26a6..e873d96 100644 --- a/Kits/DirectXTex/d3dx12.h +++ b/Kits/DirectXTex/d3dx12.h @@ -76,7 +76,12 @@ struct CD3DX12_VIEWPORT : public D3D12_VIEWPORT FLOAT minDepth = D3D12_MIN_DEPTH, FLOAT maxDepth = D3D12_MAX_DEPTH ) noexcept { +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pResource->GetDesc(&tmpDesc); +#endif const UINT64 SubresourceWidth = Desc.Width >> mipSlice; const UINT64 SubresourceHeight = Desc.Height >> mipSlice; switch (Desc.Dimension) @@ -2040,7 +2045,12 @@ inline UINT64 GetRequiredIntermediateSize( _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources) noexcept { +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif UINT64 RequiredSize = 0; ID3D12Device* pDevice = nullptr; @@ -2066,8 +2076,14 @@ inline UINT64 UpdateSubresources( _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept { // Minor validation +#if defined(_MSC_VER) || !defined(_WIN32) const auto IntermediateDesc = pIntermediate->GetDesc(); const auto DestinationDesc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc1, tmpDesc2; + const auto& IntermediateDesc = *pIntermediate->GetDesc(&tmpDesc1); + const auto& DestinationDesc = *pDestinationResource->GetDesc(&tmpDesc2); +#endif if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || RequiredSize > SIZE_T(-1) || @@ -2125,8 +2141,14 @@ inline UINT64 UpdateSubresources( _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_INFO* pSrcData) noexcept { // Minor validation +#if defined(_MSC_VER) || !defined(_WIN32) const auto IntermediateDesc = pIntermediate->GetDesc(); const auto DestinationDesc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc1, tmpDesc2; + const auto& IntermediateDesc = *pIntermediate->GetDesc(&tmpDesc1); + const auto& DestinationDesc = *pDestinationResource->GetDesc(&tmpDesc2); +#endif if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || RequiredSize > SIZE_T(-1) || @@ -2194,7 +2216,12 @@ inline UINT64 UpdateSubresources( auto pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); auto pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif ID3D12Device* pDevice = nullptr; pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast(&pDevice)); pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); @@ -2232,7 +2259,12 @@ inline UINT64 UpdateSubresources( auto pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); auto pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif ID3D12Device* pDevice = nullptr; pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast(&pDevice)); pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); @@ -2260,7 +2292,12 @@ inline UINT64 UpdateSubresources( UINT NumRows[MaxSubresources]; UINT64 RowSizesInBytes[MaxSubresources]; +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif ID3D12Device* pDevice = nullptr; pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast(&pDevice)); pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize); @@ -2287,7 +2324,12 @@ inline UINT64 UpdateSubresources( UINT NumRows[MaxSubresources]; UINT64 RowSizesInBytes[MaxSubresources]; +#if defined(_MSC_VER) || !defined(_WIN32) const auto Desc = pDestinationResource->GetDesc(); +#else + D3D12_RESOURCE_DESC tmpDesc; + const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc); +#endif ID3D12Device* pDevice = nullptr; pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast(&pDevice)); pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize); @@ -4071,20 +4113,20 @@ public: D3D12_BARRIER_SUBRESOURCE_RANGE{ Subresource, 0, 0, 0, 0, 0 } {} CD3DX12_BARRIER_SUBRESOURCE_RANGE( - UINT FirstMipLevel, - UINT NumMips, - UINT FirstArraySlice, - UINT NumArraySlices, - UINT FirstPlane = 0, - UINT NumPlanes = 1) noexcept : + UINT firstMipLevel, + UINT numMips, + UINT firstArraySlice, + UINT numArraySlices, + UINT firstPlane = 0, + UINT numPlanes = 1) noexcept : D3D12_BARRIER_SUBRESOURCE_RANGE { - FirstMipLevel, - NumMips, - FirstArraySlice, - NumArraySlices, - FirstPlane, - NumPlanes + firstMipLevel, + numMips, + firstArraySlice, + numArraySlices, + firstPlane, + numPlanes } {} }; diff --git a/Kits/LiveTK/LiveResources.cpp b/Kits/LiveTK/LiveResources.cpp index 541a5a0..34fbf29 100644 --- a/Kits/LiveTK/LiveResources.cpp +++ b/Kits/LiveTK/LiveResources.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #ifdef __clang__ @@ -41,9 +42,7 @@ namespace _Use_decl_annotations_ LiveResources::LiveResources(XTaskQueueHandle queue, bool autoManageUser, bool isGuestUserAllowed) noexcept(false): -#ifdef _GAMING_XBOX - m_networkConnectivityChangedHandle{}, -#endif + m_networkConnectivityChangedToken{}, m_isNetworkAvailable(false), m_autoManageUser(autoManageUser), m_isGuestUserAllowed(isGuestUserAllowed), @@ -74,59 +73,57 @@ LiveResources::LiveResources(XTaskQueueHandle queue, bool autoManageUser, bool i char scidBuffer[64] = {}; sprintf_s(scidBuffer, "00000000-0000-0000-0000-0000%08x", m_titleId); - + XblInitArgs xblInit = { m_asyncQueue, scidBuffer }; hr = XblInitialize(&xblInit); DX::ThrowIfFailed(hr); m_scid = scidBuffer; -#ifdef _GAMING_XBOX - if (XGameRuntimeIsFeatureAvailable(XGameRuntimeFeature::XNetworking)) - { - // Listen for network connectivity changes - NotifyNetworkConnectivityHintChange( - [](void* context, NL_NETWORK_CONNECTIVITY_HINT connectivityHint) - { - auto liveResources = static_cast(context); - - liveResources->m_isNetworkAvailable = - connectivityHint.ConnectivityLevel != NL_NETWORK_CONNECTIVITY_LEVEL_HINT::NetworkConnectivityLevelHintUnknown; - }, // Callback function - this, // Context object - true, // Notify immediately with the current status - &m_networkConnectivityChangedHandle // Notification handle - ); - } - else -#endif - { - // Assume network stack is ready on desktop - m_isNetworkAvailable = true; - } + // Listen for network connectivity changes + hr = XNetworkingRegisterConnectivityHintChanged( + m_asyncQueue, + this, + [](void* context, const XNetworkingConnectivityHint* connectivityHint) + { + auto liveResources = static_cast(context); + + liveResources->m_isNetworkAvailable = + connectivityHint->connectivityLevel != XNetworkingConnectivityLevelHint::Unknown; + }, + &m_networkConnectivityChangedToken); + DX::ThrowIfFailed(hr); + + XNetworkingConnectivityHint hint{}; + XNetworkingGetConnectivityHint(&hint); + m_isNetworkAvailable = hint.connectivityLevel != XNetworkingConnectivityLevelHint::Unknown; } LiveResources::~LiveResources() { -#ifdef _GAMING_XBOX - if (m_networkConnectivityChangedHandle) + if (m_xboxLiveContext) { - CancelMibChangeNotify2(m_networkConnectivityChangedHandle); + XblContextCloseHandle(m_xboxLiveContext); + } + if (m_xboxLiveUser) + { + XUserCloseHandle(m_xboxLiveUser); } -#endif - if (m_asyncQueue) - { - XTaskQueueCloseHandle(m_asyncQueue); - m_asyncQueue = nullptr; - } + XUserUnregisterForChangeEvent(m_userChangedEventToken, false); + XNetworkingUnregisterConnectivityHintChanged(m_networkConnectivityChangedToken, false); + + auto async = new XAsyncBlock{}; + XblCleanupAsync(async); + + XTaskQueueCloseHandle(m_asyncQueue); } void LiveResources::Initialize() { - XUserRegisterForChangeEvent(m_asyncQueue, this, [](void *context, const XUserLocalId userLocalId, XUserChangeEvent event) + XUserRegisterForChangeEvent(m_asyncQueue, this, [](void *context, const XUserLocalId userLocalId, XUserChangeEvent event) { - auto pThis = reinterpret_cast(context); + auto pThis = static_cast(context); switch (event) { @@ -281,7 +278,7 @@ void LiveResources::SignInSilently() pThis->HandleError(result); } } - + delete async; }; diff --git a/Kits/LiveTK/LiveResources.h b/Kits/LiveTK/LiveResources.h index 4323ff6..6882873 100644 --- a/Kits/LiveTK/LiveResources.h +++ b/Kits/LiveTK/LiveResources.h @@ -74,9 +74,7 @@ namespace ATG void HandleError(HRESULT error); void InitializeXboxServices(); -#ifdef _GAMING_XBOX - HANDLE m_networkConnectivityChangedHandle; -#endif + XTaskQueueRegistrationToken m_networkConnectivityChangedToken; bool m_isNetworkAvailable; bool m_autoManageUser; diff --git a/README.md b/README.md index c9cdd6b..5b71264 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ This repo contains game development samples written by the Microsoft Xbox Advanc * [Kits](/Kits) contains support code used by the samples * [Media](/Media) contains media files used by the samples -* [Samples](#Samples-by-category) contains samples - * [Audio](#Audio) - * [IntroGraphics](#Intro-Graphics) - * [Graphics](#Graphics) - * [Live](#Live) - * [System](#System) - * [Tools](#Tools) - * [xCloud](#xCloud) +* [Samples](../../../wiki/SampleList) contains samples + * [Audio](../../../wiki/SampleList#Audio) + * [IntroGraphics](../../../wiki/SampleList#Intro-Graphics) + * [Graphics](../../../wiki/SampleList#Graphics) + * [Live](../../../wiki/SampleList#Live) + * [System](../../../wiki/SampleList#System) + * [Tools](../../../wiki/SampleList#Tools) + * [xCloud](../../../wiki/SampleList#xCloud) # Requirements @@ -36,130 +36,6 @@ This project may contain trademarks or logos for projects, products, or services For more ATG samples, see [DirectML Samples](https://github.com/microsoft/DirectML), [PlayFab-Samples](https://github.com/PlayFab/PlayFab-Samples), [Xbox-ATG-Samples](https://github.com/microsoft/Xbox-ATG-Samples), and [Xbox-LIVE-Samples](https://github.com/microsoft/xbox-live-samples). -## Samples by category +## Samples list by category - -### Audio - -| Path| Xbox| PC| Tool| -|----------------------------------------| ------| ------| ------| -| AdvancedSpatialSounds| [Xbox](Samples/Audio/AdvancedSpatialSounds)| | | -| InGameChat| [Xbox](Samples/Audio/InGameChat)| [PC](Samples/Audio/InGameChat)| | -| SimplePlay3DSound| [Xbox](Samples/Audio/SimplePlay3DSound)| | | -| SimplePlaySound| [Xbox](Samples/Audio/SimplePlaySound)| | | -| SimplePlaySoundStream| [Xbox](Samples/Audio/SimplePlaySoundStream)| | | -| SimpleSpatialPlaySound| [Xbox](Samples/Audio/SimpleSpatialPlaySound)| | | -| SimpleWASAPICapture| [Xbox](Samples/Audio/SimpleWASAPICapture)| | | -| SimpleWASAPIPlaySound| [Xbox](Samples/Audio/SimpleWASAPIPlaySound)| | | - -### Graphics - -| Path| Xbox| PC| Tool| -|----------------------------------------| ------| ------| ------| -| AdvancedESRAM| [Xbox](Samples/Graphics/AdvancedESRAM)| | | -| Antialiasing| [Xbox](Samples/Graphics/Antialiasing)| | | -| ComputeParticles| [Xbox](Samples/Graphics/ComputeParticles)| | | -| DeferredParticles| [Xbox](Samples/Graphics/DeferredParticles)| | | -| DXRTriangle| [Xbox](Samples/Graphics/DXRTriangle)| [PC](Samples/Graphics/DXRTriangle)| | -| DynamicLOD| [Xbox](Samples/Graphics/DynamicLOD)| [PC](Samples/Graphics/DynamicLOD)| | -| ExecuteIndirect| [Xbox](Samples/Graphics/ExecuteIndirect)| | | -| FastBlockCompress| [Xbox](Samples/Graphics/FastBlockCompress)| | | -| GeometricExpansion| [Xbox](Samples/Graphics/GeometricExpansion)| [PC](Samples/Graphics/GeometricExpansion)| | -| HDR10| [Xbox](Samples/Graphics/HDR10)| | | -| HistogramCS| [Xbox](Samples/Graphics/HistogramCS)| | | -| HlslCompile| [Xbox](Samples/Graphics/HlslCompile)| | [Tool](Samples/Graphics/HlslCompile)| -| MeshletCull| [Xbox](Samples/Graphics/MeshletCull)| [PC](Samples/Graphics/MeshletCull)| | -| MeshletInstancing| [Xbox](Samples/Graphics/MeshletInstancing)| [PC](Samples/Graphics/MeshletInstancing)| | -| PointSprites| [Xbox](Samples/Graphics/PointSprites)| | | -| SimpleHDR| [Xbox](Samples/Graphics/SimpleHDR)| | | -| SimplePBR| [Xbox](Samples/Graphics/SimplePBR)| [PC](Samples/Graphics/SimplePBR)| | -| SimpleMeshlet| [Xbox](Samples/Graphics/SimpleMeshlet)| [PC](Samples/Graphics/SimpleMeshlet)| | -| SmokeSimulation| [Xbox](Samples/Graphics/SmokeSimulation)| | | -| VisibilityBuffer|[Xbox](Samples/Graphics/VisibilityBuffer/VisibilityBuffer)|[PC](Samples/Graphics/VisibilityBuffer/VisibilityBuffer)| | - -### IntroGraphics - -| Path| Xbox| PC| Tool| -|----------------------------------------| ------| ------| ------| -| SimpleBezier| [Xbox](Samples/IntroGraphics/SimpleBezier)| | | -| SimpleCompute| [Xbox](Samples/IntroGraphics/SimpleCompute)| | | -| SimpleDeviceAndSwapChain| [Xbox](Samples/IntroGraphics/SimpleDeviceAndSwapChain)| | | -| SimpleDynamicResources| [Xbox](Samples/IntroGraphics/SimpleDynamicResources)| [PC](Samples/IntroGraphics/SimpleDynamicResources)| | -| SimpleInstancing| [Xbox](Samples/IntroGraphics/SimpleInstancing)| | | -| SimpleLighting| [Xbox](Samples/IntroGraphics/SimpleLighting)| | | -| SimpleMeshShader| [Xbox](Samples/IntroGraphics/SimpleMeshShader)| [PC](Samples/IntroGraphics/SimpleMeshShader)| | -| SimpleMSAA| [Xbox](Samples/IntroGraphics/SimpleMSAA)| | | -| SimpleSamplerFeedback| [Xbox](Samples/IntroGraphics/SimpleSamplerFeedback)| | | -| SimpleTexture| [Xbox](Samples/IntroGraphics/SimpleTexture)| | | -| SimpleTriangle| [Xbox](Samples/IntroGraphics/SimpleTriangle)| [PC](Samples/IntroGraphics/SimpleTriangleDesktop)| | - -### Live - -| Path| Xbox| PC| Tool| -|----------------------------------------| ------| ------| ------| -| Achievements| [Xbox](Samples/Live/Achievements)| [PC](Samples/Live/Achievements)| | -| DownloadableContent| [Xbox](Samples/Live/DownloadableContent)| [PC](Samples/Live/DownloadableContent)| | -| Fundamentals| | [PC](Samples/Live/Fundamentals_Desktop)| | -| InGameStore| [Xbox](Samples/Live/InGameStore)| [PC](Samples/Live/InGameStore)| | -| LeaderboardsEventManaged| [Xbox](Samples/Live/LeaderboardsEventManaged)| [PC](Samples/Live/LeaderboardsEventManaged)| | -| LeaderboardsTitleManaged| [Xbox](Samples/Live/LeaderboardsTitleManaged)| [PC](Samples/Live/LeaderboardsTitleManaged_Desktop)| | -| mDNS| [Xbox](Samples/Live/mDNS)| [PC](Samples/Live/mDNS_Desktop)| | -| MicrosoftStoreServicesClient| [Xbox](Samples/Live/MicrosoftStoreServicesClient)| [PC](Samples/Live/MicrosoftStoreServicesClient)| | -| SimpleCrossGenMPSD| [Xbox](Samples/Live/SimpleCrossGenMPSD)| [PC](Samples/Live/SimpleCrossGenMPSD)| | -| SimpleHttp| [Xbox](Samples/Live/SimpleHttp)| [PC](Samples/Live/SimpleHttp)| | -| SimpleWebSockets| [Xbox](Samples/Live/SimpleWebSockets)| [PC](Samples/Live/SimpleWebSockets)| | -| SocialManager| [Xbox](Samples/Live/SocialManager)| [PC](Samples/Live/SocialManager)| | -| TitleStorage| [Xbox](Samples/Live/TitleStorage)| | | - -### System - -| Path| Xbox| PC| Tool| -|----------------------------------------| ------| ------| ------| -| AdvancedExceptionHandling| [Xbox](Samples/System/AdvancedExceptionHandling)| [PC](Samples/System/AdvancedExceptionHandling)| | -| OutOfProcDumpTool| [Xbox](Samples/System/AdvancedExceptionHandling)| | | -| AsynchronousProgramming| [Xbox](Samples/System/AsynchronousProgramming)| [PC](Samples/System/AsynchronousProgramming)| | -| Collision| [Xbox](Samples/System/Collision)| [PC](Samples/System/Collision)| | -| CustomEventProvider| [Xbox](Samples/System/CustomEventProvider)| | | -| DataBreakPoints| [Xbox](Samples/System/DataBreakPoints)| [PC](Samples/System/DataBreakPoints)| | -| FrontPanelDemo| [Xbox](Samples/System/FrontPanelDemo)| | | -| FrontPanelDolphin| [Xbox](Samples/System/FrontPanelDolphin)| | | -| FrontPanelGame| [Xbox](Samples/System/FrontPanelGame)| | | -| FrontPanelLogo| [Xbox](Samples/System/FrontPanelLogo)| | | -| FrontPanelText| [Xbox](Samples/System/FrontPanelText)| | | -| GameInputInterfacing| [Xbox](Samples/System/GameInputInterfacing)| | | -| GameInputSequential| [Xbox](Samples/System/GameInputSequential)| | | -| Gamepad| [Xbox](Samples/System/Gamepad)| [PC](Samples/System/Gamepad | | -| GamepadVibration| [Xbox](Samples/System/GamepadVibration)| [PC](Samples/System/GamepadVibration)| | -| GameSave| [Xbox](Samples/System/GameSave)| [PC](Samples/System/GameSave_Desktop)| | -| IntelligentDelivery| [Xbox](Samples/System/IntelligentDelivery)| [PC](Samples/System/IntelligentDelivery)| | -| LocalStorage| [Xbox](Samples/System/LocalStorage)| [PC](Samples/System/LocalStorage)| | -| MouseInput| [Xbox](Samples/System/MouseInput)| | | -| NLSAndLocalization| [Xbox](Samples/System/NLSAndLocalization)| [PC](Samples/System/NLSAndLocalization)| | -| SimpleDirectStorage| [Xbox](Samples/System/SimpleDirectStorage)| | | -| SimpleDirectStorageCombo| [Xbox](Samples/System/SimpleDirectStorageCombo)| [PC](Samples/System/SimpleDirectStorageCombo)| | -| SimpleExceptionHandling| [Xbox](Samples/System/SimpleExceptionHandling)| [PC](Samples/System/SimpleExceptionHandling)| | -| SimpleFFBWheel| [Xbox](Samples/System/SimpleFFBWheel)| | | -| SimpleFrontPanel| [Xbox](Samples/System/SimpleFrontPanel)| | | -| SimplePLM| [Xbox](Samples/System/SimplePLM)| | | -| SimpleUserModel| [Xbox](Samples/System/SimpleUserModel)| | | -| SystemInfo| [Xbox](Samples/System/SystemInfo)| [PC](Samples/System/SystemInfo)| | -| UserManagement| [Xbox](Samples/System/UserManagement)| | | - -### Tools - -| Path| Xbox| PC| Tool| -|----------------------------------------| ------| ------| ------| -| BWOIExample| [Xbox](Samples/Tools/BWOIExample)| [PC](Samples/Tools/BWOIExample)| | -| CacheTestCombo| [Xbox](Samples/Tools/CacheTestCombo)| [PC](Samples/Tools/CacheTestCombo)| | -| DumpTool| [Xbox](Samples/Tools/DumpTool)| | | -| ConverterApp| | | [Tool](Samples/Tools/MeshletConverter)| -| Runtime| | | [Tool](Samples/Tools/MeshletConverter)| -| OSPrimitiveTestCombo| [Xbox](Samples/Tools/OSPrimitiveTestCombo)| [PC](Samples/Tools/OSPrimitiveTestCombo)| | -| xbgamepad| | | [Tool](Samples/Tools/xbgamepad)| -| xtexconv| | | [Tool](Samples/Tools/xtexconv)| - -### xCloud - -| Path| Xbox| PC| Tool| -|----------------------------------------| ------| ------| ------| -| SimpleCloudAwareSample| [Xbox](Samples/xCloud/SimpleCloudAwareSample)| | | +[Samples List Wiki](../../../wiki/SampleList) diff --git a/Samples/Audio/InGameChat/InGameChat.vcxproj b/Samples/Audio/InGameChat/InGameChat.vcxproj index c134ee8..7c2b63f 100644 --- a/Samples/Audio/InGameChat/InGameChat.vcxproj +++ b/Samples/Audio/InGameChat/InGameChat.vcxproj @@ -508,7 +508,7 @@ - + diff --git a/Samples/Audio/InGameChat/InGameChat.vcxproj.filters b/Samples/Audio/InGameChat/InGameChat.vcxproj.filters index 0be37fe..47bcd50 100644 --- a/Samples/Audio/InGameChat/InGameChat.vcxproj.filters +++ b/Samples/Audio/InGameChat/InGameChat.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -118,7 +118,7 @@ - + diff --git a/Samples/Audio/InGameChat/Main.cpp b/Samples/Audio/InGameChat/Main.cpp index 9e09b43..6057d38 100644 --- a/Samples/Audio/InGameChat/Main.cpp +++ b/Samples/Audio/InGameChat/Main.cpp @@ -384,7 +384,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); diff --git a/Samples/Audio/InGameChat/MicrosoftGame.Config b/Samples/Audio/InGameChat/MicrosoftGameConfig.mgc similarity index 93% rename from Samples/Audio/InGameChat/MicrosoftGame.Config rename to Samples/Audio/InGameChat/MicrosoftGameConfig.mgc index 67f69bf..b154b3f 100644 --- a/Samples/Audio/InGameChat/MicrosoftGame.Config +++ b/Samples/Audio/InGameChat/MicrosoftGameConfig.mgc @@ -1,5 +1,5 @@ - + @@ -10,6 +10,7 @@ 6B2BEA70 + 000000004C26F118 -#if _GRDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GRDK_VER < 0x55F00C58 /* GDK Edition 220300 */ +#error This sample requires the March 2022 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT diff --git a/Samples/Graphics/AdvancedESRAM/AdvancedESRAM.cpp b/Samples/Graphics/AdvancedESRAM/AdvancedESRAM.cpp index f0494ac..40ebd42 100644 --- a/Samples/Graphics/AdvancedESRAM/AdvancedESRAM.cpp +++ b/Samples/Graphics/AdvancedESRAM/AdvancedESRAM.cpp @@ -8,7 +8,7 @@ #include "pch.h" #include "AdvancedESRAM.h" -extern void ExitSample(); +extern void ExitSample() noexcept; using namespace DirectX; using namespace ATG; @@ -107,36 +107,37 @@ namespace const std::vector s_triIndex = { 0, 1, 2 }; // Sample Constants - const DXGI_FORMAT c_colorFormat = DXGI_FORMAT_R11G11B10_FLOAT; - const DXGI_FORMAT c_depthFormat = DXGI_FORMAT_D32_FLOAT; + constexpr DXGI_FORMAT c_colorFormat = DXGI_FORMAT_R11G11B10_FLOAT; + constexpr DXGI_FORMAT c_depthFormat = DXGI_FORMAT_D32_FLOAT; - const float c_defaultPhi = XM_2PI / 6.0f; - const float c_defaultRadius = 3.3f; + constexpr float c_defaultPhi = XM_2PI / 6.0f; + constexpr float c_defaultRadius = 3.3f; //----------------------------------- // Helper Functions template - void IncrMod(T& value, T mod) { + void IncrMod(T& value, T mod) noexcept + { T res = (value + 1) % mod; value = res < 0 ? mod - 1 : res; } template - void DecrMod(T& value, T mod) { + void DecrMod(T& value, T mod) noexcept + { int res = int(value) - 1; value = res < 0 ? mod - 1 : res; } - void Saturate(float& value) { value = std::max(0.0f, std::min(1.0f, value)); } + void Saturate(float& value) noexcept { value = std::max(0.0f, std::min(1.0f, value)); } } #pragma endregion #pragma region Construction -Sample::Sample() - : m_deviceResources(new DX::DeviceResources(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN)) - , m_displayWidth(0) +Sample::Sample() noexcept(false) + : m_displayWidth(0) , m_displayHeight(0) , m_frame(0) , m_theta(0.0f) @@ -148,7 +149,9 @@ Sample::Sample() , m_updateStats(true) , m_visData{} { - std::fill_n(m_esramRatios, _countof(m_esramRatios), 1.0f); + m_deviceResources = std::make_unique(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + + std::fill_n(m_esramRatios, std::size(m_esramRatios), 1.0f); } Sample::~Sample() @@ -188,6 +191,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); @@ -196,10 +201,11 @@ void Sample::Tick() Render(); PIXEndEvent(); - ++m_frame; + m_frame++; } -void Sample::Update(const DX::StepTimer& timer) +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) { using ButtonState = DirectX::GamePad::ButtonStateTracker::ButtonState; @@ -326,6 +332,7 @@ void Sample::Update(const DX::StepTimer& timer) #pragma region Frame Render +// Draws the scene. void Sample::Render() { // Don't try to render anything before the first Update. @@ -360,14 +367,14 @@ void Sample::Render() // Set descriptor heaps ID3D12DescriptorHeap* heaps[] = { m_srvPile->Heap(), m_commonStates->Heap() }; - commandList->SetDescriptorHeaps(UINT(_countof(heaps)), heaps); + commandList->SetDescriptorHeaps(static_cast(std::size(heaps)), heaps); { ScopedPixEvent Clear(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -412,10 +419,11 @@ void Sample::Render() TransientResource outlineTex[2]; D3D12_GPU_DESCRIPTOR_HANDLE srvHandles[2]; - for (uint32_t i = 0; i < _countof(outlineTex); ++i) + for (size_t i = 0; i < std::size(outlineTex); ++i) { outlineTex[i] = AcquireTransientTexture(commandList, m_outlineDesc, D3D12_RESOURCE_STATE_RENDER_TARGET, SceneTexture(ST_Outline0 + i)); - srvHandles[i] = m_srvPile->WriteDescriptors(m_deviceResources->GetD3DDevice(), SRV_Outline0 + i, &outlineTex[i].SRV, 1); + srvHandles[i] = m_srvPile->WriteDescriptors(m_deviceResources->GetD3DDevice(), + static_cast(SRV_Outline0 + i), &outlineTex[i].SRV, 1); handles[ST_Outline0 + i] = outlineTex[i].handle; } @@ -454,7 +462,7 @@ void Sample::Render() obj.model->DrawOpaque(commandList, obj.effects.begin()); // Release the outline textures' memory pages back to the allocator. - for (uint32_t i = 0; i < _countof(outlineTex); ++i) + for (size_t i = 0; i < std::size(outlineTex); ++i) { m_allocator->Release(commandList, outlineTex[i], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); } @@ -476,10 +484,11 @@ void Sample::Render() TransientResource bloomTex[2]; D3D12_GPU_DESCRIPTOR_HANDLE srvHandles[2]; - for (uint32_t i = 0; i < _countof(bloomTex); ++i) + for (size_t i = 0; i < std::size(bloomTex); ++i) { bloomTex[i] = AcquireTransientTexture(commandList, m_bloomDesc, D3D12_RESOURCE_STATE_RENDER_TARGET, SceneTexture(ST_Bloom0 + i)); - srvHandles[i] = m_srvPile->WriteDescriptors(m_deviceResources->GetD3DDevice(), SRV_Bloom0 + i, &bloomTex[i].SRV, 1); + srvHandles[i] = m_srvPile->WriteDescriptors(m_deviceResources->GetD3DDevice(), + static_cast(SRV_Bloom0 + i), &bloomTex[i].SRV, 1); handles[ST_Bloom0 + i] = bloomTex[i].handle; } @@ -540,7 +549,7 @@ void Sample::Render() commandList->CopyResource(colorTex.resource, bloomTex[1].resource); // We're finished with the bloom textures - release their memory pages back to the allocator. - for (uint32_t i = 0; i < _countof(bloomTex); ++i) + for (size_t i = 0; i < std::size(bloomTex); ++i) { m_allocator->Release(commandList, bloomTex[i], D3D12_RESOURCE_STATE_GENERIC_READ); } @@ -613,7 +622,7 @@ void Sample::DrawHUD(ID3D12GraphicsCommandList* commandList) { m_hudBatch->Begin(commandList); - auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(m_displayWidth, m_displayHeight); + auto const safe = SimpleMath::Viewport::ComputeTitleSafeArea(m_displayWidth, m_displayHeight); wchar_t textBuffer[128] = {}; XMFLOAT2 textPos = XMFLOAT2(float(safe.left), float(safe.top)); @@ -748,13 +757,11 @@ void Sample::CreateDeviceDependentResources() // Create heap m_srvPile = std::make_unique(device, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 128, DescriptorHeapIndex::SRV_Count); // Load models from disk. - m_models.resize(_countof(s_modelPaths)); + m_models.resize(std::size(s_modelPaths)); for (size_t i = 0; i < m_models.size(); ++i) { m_models[i] = Model::CreateFromSDKMESH(device, s_modelPaths[i]); @@ -782,8 +789,8 @@ void Sample::CreateDeviceDependentResources() } // HUD - auto backBufferRts = RenderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); - auto spritePSD = SpriteBatchPipelineStateDescription(backBufferRts, &CommonStates::AlphaBlend); + const RenderTargetState backBufferRts(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const SpriteBatchPipelineStateDescription spritePSD(backBufferRts, &CommonStates::AlphaBlend); m_hudBatch = std::make_unique(device, resourceUpload, spritePSD); auto finished = resourceUpload.End(m_deviceResources->GetCommandQueue()); @@ -795,8 +802,8 @@ void Sample::CreateDeviceDependentResources() auto effectFactory = EffectFactory(m_srvPile->Heap(), m_commonStates->Heap()); - auto objectRTState = RenderTargetState(c_colorFormat, c_depthFormat); - auto objectPSD = EffectPipelineStateDescription( + const RenderTargetState objectRTState(c_colorFormat, c_depthFormat); + const EffectPipelineStateDescription objectPSD( nullptr, CommonStates::Opaque, CommonStates::DepthDefault, @@ -804,7 +811,7 @@ void Sample::CreateDeviceDependentResources() objectRTState, D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE); - m_scene.resize(_countof(s_sceneDefinition)); + m_scene.resize(std::size(s_sceneDefinition)); for (size_t i = 0; i < m_scene.size(); i++) { size_t index = s_sceneDefinition[i].modelIndex; @@ -825,8 +832,8 @@ void Sample::CreateDeviceDependentResources() }); } - auto outlineRtState = RenderTargetState(c_colorFormat, DXGI_FORMAT_UNKNOWN); - auto outlinePSD = EffectPipelineStateDescription( + const RenderTargetState outlineRtState(c_colorFormat, DXGI_FORMAT_UNKNOWN); + const EffectPipelineStateDescription outlinePSD( &VertexPositionNormalTexture::InputLayout, CommonStates::Opaque, CommonStates::DepthNone, @@ -842,11 +849,11 @@ void Sample::CreateDeviceDependentResources() m_fullScreenTri = GeometricPrimitive::CreateCustom(s_triVertex, s_triIndex); - auto postRtState = RenderTargetState(c_colorFormat, DXGI_FORMAT_UNKNOWN); + const RenderTargetState postRtState(c_colorFormat, DXGI_FORMAT_UNKNOWN); m_blurEffect = std::make_unique(device, postRtState, BasicPostProcess::GaussianBlur_5x5); m_blurEffect->SetGaussianParameter(12.0f); - auto combinePSD = EffectPipelineStateDescription( + const EffectPipelineStateDescription combinePSD( &VertexPositionNormalTexture::InputLayout, CommonStates::NonPremultiplied, CommonStates::DepthNone, @@ -859,7 +866,7 @@ void Sample::CreateDeviceDependentResources() m_alphaCompositeEffect->SetDiffuseColor(XMVectorSet(1.0f, 1.0f, 1.0f, 1.0f)); m_alphaCompositeEffect->SetAlpha(0.6f); - auto backBufferRtState = RenderTargetState(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + const RenderTargetState backBufferRtState(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); m_bloomExtractEffect = std::make_unique(device, postRtState, BasicPostProcess::BloomExtract); m_bloomExtractEffect->SetBloomExtractParameter(0.9f); @@ -988,7 +995,7 @@ void Sample::UpdateVisualizerRanges(const ResourceHandle(&resources)[ST_Count]) // Calculate ESRAM page ranges for each texture std::vector ranges; - for (size_t i = 0; i < _countof(resources); ++i) + for (size_t i = 0; i < std::size(resources); ++i) { #ifdef _GAMING_XBOX_XBOXONE m_allocator->GetEsramRanges(resources[i], ranges); diff --git a/Samples/Graphics/AdvancedESRAM/AdvancedESRAM.h b/Samples/Graphics/AdvancedESRAM/AdvancedESRAM.h index de59a45..8b8c53b 100644 --- a/Samples/Graphics/AdvancedESRAM/AdvancedESRAM.h +++ b/Samples/Graphics/AdvancedESRAM/AdvancedESRAM.h @@ -46,25 +46,33 @@ enum SceneTexture : uint32_t class Sample { public: - Sample(); + Sample() noexcept(false); ~Sample(); + Sample(Sample&&) = default; + Sample& operator= (Sample&&) = default; + + Sample(Sample const&) = delete; + Sample& operator= (Sample const&) = delete; + // Initialization and management void Initialize(HWND window); void Uninitialize(); - // Basic Sample loop + // Basic render loop void Tick(); // Messages void OnSuspending(); void OnResuming(); + void OnConstrained() {} + void OnUnConstrained() {} // Properties - bool RequestHDRMode() const { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } + bool RequestHDRMode() const noexcept { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } private: - void Update(const DX::StepTimer& timer); + void Update(DX::StepTimer const& timer); void Render(); void DrawHUD(ID3D12GraphicsCommandList* commandList); diff --git a/Samples/Graphics/AdvancedESRAM/DeviceResources.cpp b/Samples/Graphics/AdvancedESRAM/DeviceResources.cpp index d76fd63..fa67816 100644 --- a/Samples/Graphics/AdvancedESRAM/DeviceResources.cpp +++ b/Samples/Graphics/AdvancedESRAM/DeviceResources.cpp @@ -31,14 +31,13 @@ DeviceResources::DeviceResources( m_rtvDescriptorSize(0), m_screenViewport{}, m_scissorRect{}, - m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_backBufferFormat(backBufferFormat), m_depthBufferFormat(depthBufferFormat), m_backBufferCount(backBufferCount), m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), m_outputSize{0, 0, 1920, 1080}, - m_options(flags), - m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) + m_options(flags) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) { @@ -55,12 +54,16 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } } // Configures the Direct3D device, and stores handles to it and the device context. +#ifdef _GAMING_XBOX_SCARLETT +void DeviceResources::CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags) +#else void DeviceResources::CreateDeviceResources() +#endif { // Create the DX12 API device object. D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; @@ -77,6 +80,17 @@ void DeviceResources::CreateDeviceResources() params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#ifdef _GAMING_XBOX_SCARLETT + params.CreateDeviceFlags = createDeviceFlags; + +#if (_GXDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif +#endif HRESULT hr = D3D12XboxCreateDevice( nullptr, @@ -107,7 +121,7 @@ void DeviceResources::CreateDeviceResources() // Create descriptor heaps for render target views and depth stencil views. D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; - rtvDescriptorHeapDesc.NumDescriptors = (m_options & c_EnableHDR) ? (m_backBufferCount * 2) : m_backBufferCount; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); @@ -152,31 +166,46 @@ void DeviceResources::CreateDeviceResources() m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { - throw std::exception("CreateEvent"); + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } - if (m_options & c_Enable4K_UHD) + if (m_options & (c_Enable4K_UHD | c_EnableQHD)) { switch (XSystemGetDeviceType()) { case XSystemDeviceType::XboxOne: case XSystemDeviceType::XboxOneS: - case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: - m_options &= ~c_Enable4K_UHD; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080)\n"); -#endif + m_options &= ~(c_Enable4K_UHD | c_EnableQHD); break; + case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: + m_options &= ~c_Enable4K_UHD; + if (m_options & c_EnableQHD) + { + m_outputSize = { 0, 0, 2560, 1440 }; + } + break; + + case XSystemDeviceType::XboxScarlettAnaconda /* Xbox Series X */: + case XSystemDeviceType::XboxOneXDevkit: + case XSystemDeviceType::XboxScarlettDevkit: default: - m_outputSize = { 0, 0, 3840, 2160 }; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160)\n"); -#endif + m_outputSize = (m_options & c_Enable4K_UHD) ? RECT{ 0, 0, 3840, 2160 } : RECT{ 0, 0, 2560, 1440 }; break; } } +#ifdef _DEBUG + const char* info = nullptr; + switch (m_outputSize.bottom) + { + case 2160: info = "INFO: Swapchain using 4k (3840 x 2160)\n"; break; + case 1440: info = "INFO: Swapchain using 1440p (2560 x 1440)\n"; break; + default: info = "INFO: Swapchain using 1080p (1920 x 1080)\n"; break; + } + OutputDebugStringA(info); +#endif + RegisterFrameEvents(); } @@ -185,7 +214,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { if (!m_window) { - throw std::exception("Call SetWindow with a valid window handle"); + throw std::logic_error("Call SetWindow with a valid Win32 window handle"); } // Wait until all previous GPU work is complete. @@ -198,7 +227,6 @@ void DeviceResources::CreateWindowSizeDependentResources() for (UINT n = 0; n < m_backBufferCount; n++) { m_renderTargets[n].Reset(); - m_renderTargetsGameDVR[n].Reset(); m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; } @@ -208,7 +236,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -219,6 +247,13 @@ void DeviceResources::CreateWindowSizeDependentResources() ); swapChainBufferDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; +#ifdef _GAMING_XBOX_XBOXONE + if (m_options & c_EnableHDR) + { + swapChainBufferDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_AUTOMATIC_GAMEDVR_TONE_MAP; + } +#endif + D3D12_CLEAR_VALUE swapChainOptimizedClearValue = {}; swapChainOptimizedClearValue.Format = m_backBufferFormat; @@ -240,41 +275,12 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); } - if (m_options & c_EnableHDR) - { - swapChainBufferDesc.Format = swapChainOptimizedClearValue.Format = m_gameDVRFormat; - - for (UINT n = 0; n < m_backBufferCount; n++) - { - ThrowIfFailed(m_d3dDevice->CreateCommittedResource( - &swapChainHeapProperties, - D3D12_HEAP_FLAG_ALLOW_DISPLAY, - &swapChainBufferDesc, - D3D12_RESOURCE_STATE_PRESENT, - &swapChainOptimizedClearValue, - IID_GRAPHICS_PPV_ARGS(m_renderTargetsGameDVR[n].GetAddressOf()))); - - wchar_t name[25] = {}; - swprintf_s(name, L"GameDVR Render target %u", n); - m_renderTargetsGameDVR[n]->SetName(name); - - D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; - rtvDesc.Format = m_gameDVRFormat; - rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + n), m_rtvDescriptorSize); - m_d3dDevice->CreateRenderTargetView(m_renderTargetsGameDVR[n].Get(), &rtvDesc, rtvDescriptorGameDVR); - } - } - // Reset the index to the current back buffer. m_backBufferIndex = 0; @@ -282,7 +288,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -295,7 +301,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -331,10 +337,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -342,23 +344,10 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), - beforeState, afterState), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, afterState); + m_commandList->ResourceBarrier(1, &barrier); } } @@ -368,20 +357,10 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); } // Send the command list off to the GPU for processing. @@ -389,32 +368,24 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); // Present the backbuffer using the PresentX API. - D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters[2] = {}; - planeParameters[0].Token = planeParameters[1].Token = m_framePipelineToken; - planeParameters[0].ResourceCount = planeParameters[1].ResourceCount = 1; - planeParameters[0].ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); + D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters = {}; + planeParameters.Token = m_framePipelineToken; + planeParameters.ResourceCount = 1; + planeParameters.ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); if (m_options & c_EnableHDR) { - planeParameters[0].pSrcViewRects = planeParameters[1].pSrcViewRects = &m_outputSize; - planeParameters[0].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; - planeParameters[1].ppResources = m_renderTargetsGameDVR[m_backBufferIndex].GetAddressOf(); - planeParameters[1].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; - - ThrowIfFailed( - m_commandQueue->PresentX(2, planeParameters, params) - ); - } - else - { - ThrowIfFailed( - m_commandQueue->PresentX(1, planeParameters, params) - ); + planeParameters.ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; } - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + ThrowIfFailed( + m_commandQueue->PresentX(1, &planeParameters, params) + ); - MoveToNextFrame(); + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -436,13 +407,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -451,25 +422,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/Graphics/AdvancedESRAM/DeviceResources.h b/Samples/Graphics/AdvancedESRAM/DeviceResources.h index 00b0984..4924894 100644 --- a/Samples/Graphics/AdvancedESRAM/DeviceResources.h +++ b/Samples/Graphics/AdvancedESRAM/DeviceResources.h @@ -10,8 +10,11 @@ namespace DX class DeviceResources { public: - static constexpr unsigned int c_Enable4K_UHD = 0x1; - static constexpr unsigned int c_EnableHDR = 0x2; + static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_ReverseDepth = 0x8; + static constexpr unsigned int c_AmplificationShaders = 0x10; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -25,7 +28,11 @@ namespace DX DeviceResources(DeviceResources const&) = delete; DeviceResources& operator= (DeviceResources const&) = delete; +#ifdef _GAMING_XBOX_SCARLETT + void CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags = D3D12XBOX_CREATE_DEVICE_FLAG_NONE); +#else void CreateDeviceResources(); +#endif void CreateWindowSizeDependentResources(); void SetWindow(HWND window) noexcept { m_window = window; } void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT, @@ -35,6 +42,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -67,19 +75,7 @@ namespace DX return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); } - // Direct3D HDR Game DVR support for Xbox One. - ID3D12Resource* GetGameDVRRenderTarget() const noexcept { return m_renderTargetsGameDVR[m_backBufferIndex].Get(); } - DXGI_FORMAT GetGameDVRFormat() const noexcept { return m_gameDVRFormat; } - - CD3DX12_CPU_DESCRIPTOR_HANDLE GetGameDVRRenderTargetView() const noexcept - { - return CD3DX12_CPU_DESCRIPTOR_HANDLE( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + m_backBufferIndex), m_rtvDescriptorSize); - } - private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; @@ -87,8 +83,13 @@ namespace DX UINT m_backBufferIndex; // Direct3D objects. - Microsoft::WRL::ComPtr m_d3dDevice; +#ifdef _GAMING_XBOX_SCARLETT + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandList; +#else + Microsoft::WRL::ComPtr m_d3dDevice; Microsoft::WRL::ComPtr m_commandList; +#endif Microsoft::WRL::ComPtr m_commandQueue; Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; @@ -121,9 +122,5 @@ namespace DX // DeviceResources options (see flags above) unsigned int m_options; - - // Direct3D HDR Game DVR support for Xbox One. - Microsoft::WRL::ComPtr m_renderTargetsGameDVR[MAX_BACK_BUFFER_COUNT]; - DXGI_FORMAT m_gameDVRFormat; }; } diff --git a/Samples/Graphics/AdvancedESRAM/Main.cpp b/Samples/Graphics/AdvancedESRAM/Main.cpp index 64b3364..2437de3 100644 --- a/Samples/Graphics/AdvancedESRAM/Main.cpp +++ b/Samples/Graphics/AdvancedESRAM/Main.cpp @@ -1,7 +1,7 @@ //-------------------------------------------------------------------------------------- // Main.cpp // -// Entry point for Microsoft GDK with Xbox extensions. +// Entry point for Microsoft GDK with Xbox extensions // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. @@ -18,16 +18,25 @@ using namespace DirectX; +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +#pragma warning(disable : 4061) + namespace { std::unique_ptr g_sample; HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; -}; +} bool g_HDRMode = false; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void SetDisplayMode() noexcept; +void ExitSample() noexcept; // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) @@ -58,6 +67,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp // Register class and create window PAPPSTATE_REGISTRATION hPLM = {}; + PAPPCONSTRAIN_REGISTRATION hPLM2 = {}; + { // Register class WNDCLASSEXA wcex = {}; @@ -66,7 +77,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.lpszClassName = u8"PointSpritesWindowClass"; - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); if (!RegisterClassExA(&wcex)) return 1; @@ -79,17 +90,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp ShowWindow(hwnd, nCmdShow); - if (g_sample->RequestHDRMode()) - { - // Request HDR mode. - auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); - - g_HDRMode = (result == XDisplayHdrModeResult::Enabled); - -#ifdef _DEBUG - OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); -#endif - } + SetDisplayMode(); SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(g_sample.get())); @@ -116,7 +117,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -124,6 +125,13 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp } }, hwnd, &hPLM)) return 1; + + if (RegisterAppConstrainedChangeNotification([](BOOLEAN constrained, PVOID context) + { + // To ensure we use the main UI thread to process the notification, we self-post a message + SendMessage(reinterpret_cast(context), WM_USER + 1, (constrained) ? 1u : 0u, 0); + }, hwnd, &hPLM2)) + return 1; } // Main message loop @@ -144,13 +152,14 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp g_sample.reset(); UnregisterAppStateChangeNotification(hPLM); + UnregisterAppConstrainedChangeNotification(hPLM2); CloseHandle(g_plmSuspendComplete); CloseHandle(g_plmSignalResume); XGameRuntimeUninitialize(); - return (int)msg.wParam; + return static_cast(msg.wParam); } // Windows procedure @@ -168,18 +177,52 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); + + SetDisplayMode(); sample->OnResuming(); } break; + + case WM_USER + 1: + if (sample) + { + if (wParam) + { + sample->OnConstrained(); + } + else + { + SetDisplayMode(); + + sample->OnUnConstrained(); + } + } + break; } return DefWindowProc(hWnd, message, wParam, lParam); } +// HDR helper +void SetDisplayMode() noexcept +{ + if (g_sample && g_sample->RequestHDRMode()) + { + // Request HDR mode. + auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); + + g_HDRMode = (result == XDisplayHdrModeResult::Enabled); + +#ifdef _DEBUG + OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); +#endif + } +} + // Exit helper -void ExitSample() +void ExitSample() noexcept { PostQuitMessage(0); } diff --git a/Samples/Graphics/AdvancedESRAM/ReadMe.docx b/Samples/Graphics/AdvancedESRAM/ReadMe.docx index ed37588..6cf09c9 100644 Binary files a/Samples/Graphics/AdvancedESRAM/ReadMe.docx and b/Samples/Graphics/AdvancedESRAM/ReadMe.docx differ diff --git a/Samples/Graphics/AdvancedESRAM/StepTimer.h b/Samples/Graphics/AdvancedESRAM/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/AdvancedESRAM/StepTimer.h +++ b/Samples/Graphics/AdvancedESRAM/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/AdvancedESRAM/pch.h b/Samples/Graphics/AdvancedESRAM/pch.h index 790527c..5a030a4 100644 --- a/Samples/Graphics/AdvancedESRAM/pch.h +++ b/Samples/Graphics/AdvancedESRAM/pch.h @@ -37,8 +37,8 @@ #include -#if _GXDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GXDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -59,25 +59,30 @@ #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include -#include +#include +#include +#include #include +#include -#include -#include #include #include #include #include -#include "ATGColors.h" #include "CommonStates.h" -#include "ControllerFont.h" #include "DescriptorHeap.h" #include "DirectXHelpers.h" #include "Effects.h" @@ -85,9 +90,7 @@ #include "GeometricPrimitive.h" #include "GraphicsMemory.h" #include "Model.h" -#include "PerformanceTimersXbox.h" #include "PostProcess.h" -#include "ReadData.h" #include "RenderTargetState.h" #include "ResourceUploadBatch.h" #include "SimpleMath.h" @@ -95,6 +98,11 @@ #include "SpriteFont.h" #include "VertexTypes.h" +#include "ATGColors.h" +#include "ControllerFont.h" +#include "PerformanceTimersXbox.h" +#include "ReadData.h" + #include "SharedDefinitions.h" namespace DX @@ -103,7 +111,7 @@ namespace DX class com_exception : public std::exception { public: - com_exception(HRESULT hr) : result(hr) {} + com_exception(HRESULT hr) noexcept : result(hr) {} const char* what() const override { @@ -121,6 +129,12 @@ namespace DX { if (FAILED(hr)) { +#ifdef _DEBUG + char str[64] = {}; + sprintf_s(str, "**ERROR** Fatal Error with HRESULT of %08X\n", static_cast(hr)); + OutputDebugStringA(str); + __debugbreak(); +#endif throw com_exception(hr); } } diff --git a/Samples/Graphics/Antialiasing/Antialiasing.cpp b/Samples/Graphics/Antialiasing/Antialiasing.cpp index 5813532..947bfba 100644 --- a/Samples/Graphics/Antialiasing/Antialiasing.cpp +++ b/Samples/Graphics/Antialiasing/Antialiasing.cpp @@ -137,6 +137,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); @@ -226,8 +228,8 @@ void Sample::Update(DX::StepTimer const&) } // Limit to avoid looking directly up or down - const float limit = XM_PI / 2.0f - 0.01f; - m_pitch = std::max(-limit, std::min(+limit, m_pitch)); + constexpr float c_limit = XM_PI / 2.0f - 0.01f; + m_pitch = std::max(-c_limit, std::min(+c_limit, m_pitch)); if (m_yaw > XM_PI) { @@ -386,7 +388,7 @@ void Sample::Render() { case AntialiasMethods::SMAA2X: { - auto size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); SMAAConstantBuffer cb = { { 1.f, 1.f, 1.f, 0.f }, 1.f / float(size.right), 1.f / float(size.bottom) }; auto cbHandle = m_graphicsMemory->AllocateConstant(cb); RenderSMAA(commandList, Descriptors::SceneTex, Descriptors::DepthTex, 1.f, cbHandle.GpuAddress()); @@ -406,7 +408,7 @@ void Sample::Render() commandList->ResourceBarrier(1, &barrier); } - auto size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); SMAAConstantBuffer cb = { { 0.f, 0.f, 0.f, 0.f }, 1.f / float(size.right), 1.f / float(size.bottom) }; auto cbHandle = m_graphicsMemory->AllocateConstant(cb); RenderSMAA(commandList, Descriptors::SceneTex, m_hardwareAA ? Descriptors::DepthTex : Descriptors::DepthStencilSRV, 1.f, cbHandle.GpuAddress()); @@ -425,13 +427,13 @@ void Sample::Render() { PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render FXAA"); - auto rtvDescriptor = m_renderDescriptors->GetCpuHandle(RTDescriptors::FinalRTV); + auto const rtvDescriptor = m_renderDescriptors->GetCpuHandle(RTDescriptors::FinalRTV); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, nullptr); m_scene->TransitionTo(commandList, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); m_final->BeginScene(commandList); - auto size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); FXAAConstantBuffer cb = { 1.f / float(size.right), 1.f / float(size.bottom) }; auto cbHandle = m_graphicsMemory->AllocateConstant(cb); @@ -451,7 +453,7 @@ void Sample::Render() } // Render final scene - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, nullptr); @@ -517,10 +519,10 @@ void Sample::RenderZoom(ID3D12GraphicsCommandList* commandList) m_fullScreenQuad->Draw(commandList, m_zoomPSO.Get(), m_resourceDescriptors->GetGpuHandle(Descriptors::FinalTex)); - auto vp = m_deviceResources->GetScreenViewport(); + auto const vp = m_deviceResources->GetScreenViewport(); commandList->RSSetViewports(1, &vp); - auto scissors = m_deviceResources->GetScissorRect(); + auto const scissors = m_deviceResources->GetScissorRect(); commandList->RSSetScissorRects(1, &scissors); m_lineEFfect->Apply(commandList); @@ -554,8 +556,8 @@ void Sample::RenderUI(ID3D12GraphicsCommandList* commandList) }; commandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps); - auto size = m_deviceResources->GetOutputSize(); - auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(UINT(size.right), UINT(size.bottom)); + auto const size = m_deviceResources->GetOutputSize(); + auto const safe = SimpleMath::Viewport::ComputeTitleSafeArea(UINT(size.right), UINT(size.bottom)); m_batch->Begin(commandList); @@ -683,7 +685,7 @@ void Sample::RenderSMAA(ID3D12GraphicsCommandList* commandList, size_t renderTar commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, nullptr); - float factor[4] = { blendFactor, blendFactor, blendFactor, blendFactor }; + const float factor[4] = { blendFactor, blendFactor, blendFactor, blendFactor }; commandList->OMSetBlendFactor(factor); m_fullScreenQuad->Draw(commandList, m_neighborBlendPSO.Get(), colorHandle, @@ -730,8 +732,8 @@ void Sample::Clear() commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -789,7 +791,7 @@ void Sample::CreateDeviceDependentResources() m_model->LoadStaticBuffers(device, upload); - RenderTargetState rtStateUI(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState rtStateUI(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); { SpriteBatchPipelineStateDescription pd(rtStateUI, &CommonStates::AlphaBlend); @@ -1111,7 +1113,7 @@ void Sample::CreateWindowSizeDependentResources() { m_batch->SetViewport(m_deviceResources->GetScreenViewport()); - auto size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); auto device = m_deviceResources->GetD3DDevice(); ResourceUploadBatch resourceUpload(device); diff --git a/Samples/Graphics/Antialiasing/Antialiasing.h b/Samples/Graphics/Antialiasing/Antialiasing.h index 7388a84..d61b4d6 100644 --- a/Samples/Graphics/Antialiasing/Antialiasing.h +++ b/Samples/Graphics/Antialiasing/Antialiasing.h @@ -37,6 +37,11 @@ public: // Messages void OnSuspending(); void OnResuming(); + void OnConstrained() {} + void OnUnConstrained() {} + + // Properties + bool RequestHDRMode() const noexcept { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } private: diff --git a/Samples/Graphics/Antialiasing/DeviceResources.cpp b/Samples/Graphics/Antialiasing/DeviceResources.cpp index 1b11747..c7045e9 100644 --- a/Samples/Graphics/Antialiasing/DeviceResources.cpp +++ b/Samples/Graphics/Antialiasing/DeviceResources.cpp @@ -33,7 +33,7 @@ namespace default: return fmt; } } -}; +} // Constructor for DeviceResources. DeviceResources::DeviceResources( @@ -70,12 +70,16 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } } // Configures the Direct3D device, and stores handles to it and the device context. +#ifdef _GAMING_XBOX_SCARLETT +void DeviceResources::CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags) +#else void DeviceResources::CreateDeviceResources() +#endif { // Create the DX12 API device object. D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; @@ -92,6 +96,17 @@ void DeviceResources::CreateDeviceResources() params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#ifdef _GAMING_XBOX_SCARLETT + params.CreateDeviceFlags = createDeviceFlags; + +#if (_GXDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif +#endif HRESULT hr = D3D12XboxCreateDevice( nullptr, @@ -167,31 +182,46 @@ void DeviceResources::CreateDeviceResources() m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { - throw std::exception("CreateEvent"); + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } - if (m_options & c_Enable4K_UHD) + if (m_options & (c_Enable4K_UHD | c_EnableQHD)) { switch (XSystemGetDeviceType()) { case XSystemDeviceType::XboxOne: case XSystemDeviceType::XboxOneS: - case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: - m_options &= ~c_Enable4K_UHD; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080)\n"); -#endif + m_options &= ~(c_Enable4K_UHD | c_EnableQHD); break; + case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: + m_options &= ~c_Enable4K_UHD; + if (m_options & c_EnableQHD) + { + m_outputSize = { 0, 0, 2560, 1440 }; + } + break; + + case XSystemDeviceType::XboxScarlettAnaconda /* Xbox Series X */: + case XSystemDeviceType::XboxOneXDevkit: + case XSystemDeviceType::XboxScarlettDevkit: default: - m_outputSize = { 0, 0, 3840, 2160 }; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160)\n"); -#endif + m_outputSize = (m_options & c_Enable4K_UHD) ? RECT{ 0, 0, 3840, 2160 } : RECT{ 0, 0, 2560, 1440 }; break; } } +#ifdef _DEBUG + const char* info = nullptr; + switch (m_outputSize.bottom) + { + case 2160: info = "INFO: Swapchain using 4k (3840 x 2160)\n"; break; + case 1440: info = "INFO: Swapchain using 1440p (2560 x 1440)\n"; break; + default: info = "INFO: Swapchain using 1080p (1920 x 1080)\n"; break; + } + OutputDebugStringA(info); +#endif + RegisterFrameEvents(); } @@ -200,7 +230,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { if (!m_window) { - throw std::exception("Call SetWindow with a valid window handle"); + throw std::logic_error("Call SetWindow with a valid Win32 window handle"); } // Wait until all previous GPU work is complete. @@ -222,7 +252,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -233,6 +263,13 @@ void DeviceResources::CreateWindowSizeDependentResources() ); swapChainBufferDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; +#ifdef _GAMING_XBOX_XBOXONE + if (m_options & c_EnableHDR) + { + swapChainBufferDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_AUTOMATIC_GAMEDVR_TONE_MAP; + } +#endif + D3D12_CLEAR_VALUE swapChainOptimizedClearValue = {}; swapChainOptimizedClearValue.Format = m_backBufferFormat; @@ -254,7 +291,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -267,7 +304,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( MakeDepthTypeless(m_depthBufferFormat), @@ -280,7 +317,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -316,29 +353,29 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); if (beforeState != afterState) { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + // Transition the render target into the correct state to allow for drawing into it. + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState); m_commandList->ResourceBarrier(1, &barrier); } } // Present the contents of the swap chain to the screen. -void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) +void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const D3D12XBOX_PRESENT_PARAMETERS* params) { if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); m_commandList->ResourceBarrier(1, &barrier); } @@ -347,18 +384,24 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); // Present the backbuffer using the PresentX API. - D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters[2] = {}; - planeParameters[0].Token = planeParameters[1].Token = m_framePipelineToken; - planeParameters[0].ResourceCount = planeParameters[1].ResourceCount = 1; - planeParameters[0].ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); + D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters = {}; + planeParameters.Token = m_framePipelineToken; + planeParameters.ResourceCount = 1; + planeParameters.ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); + + if (m_options & c_EnableHDR) + { + planeParameters.ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; + } ThrowIfFailed( - m_commandQueue->PresentX(1, planeParameters, nullptr) + m_commandQueue->PresentX(1, &planeParameters, params) ); - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -380,13 +423,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -395,25 +438,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/Graphics/Antialiasing/DeviceResources.h b/Samples/Graphics/Antialiasing/DeviceResources.h index f32d1b7..eef98b3 100644 --- a/Samples/Graphics/Antialiasing/DeviceResources.h +++ b/Samples/Graphics/Antialiasing/DeviceResources.h @@ -1,6 +1,8 @@ // // DeviceResources.h - A wrapper for the Direct3D 12.X device and swapchain // +// Modified to use a typeless format for depth +// #pragma once @@ -10,7 +12,11 @@ namespace DX class DeviceResources { public: - static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_ReverseDepth = 0x8; + static constexpr unsigned int c_AmplificationShaders = 0x10; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -24,15 +30,21 @@ namespace DX DeviceResources(DeviceResources const&) = delete; DeviceResources& operator= (DeviceResources const&) = delete; +#ifdef _GAMING_XBOX_SCARLETT + void CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags = D3D12XBOX_CREATE_DEVICE_FLAG_NONE); +#else void CreateDeviceResources(); +#endif void CreateWindowSizeDependentResources(); void SetWindow(HWND window) noexcept { m_window = window; } void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATES afterState = D3D12_RESOURCE_STATE_RENDER_TARGET); - void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET); + void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET, + _In_opt_ const D3D12XBOX_PRESENT_PARAMETERS* params = nullptr); void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -66,7 +78,6 @@ namespace DX } private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; diff --git a/Samples/Graphics/Antialiasing/Main.cpp b/Samples/Graphics/Antialiasing/Main.cpp index df7111c..59fddbb 100644 --- a/Samples/Graphics/Antialiasing/Main.cpp +++ b/Samples/Graphics/Antialiasing/Main.cpp @@ -18,16 +18,25 @@ using namespace DirectX; +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +#pragma warning(disable : 4061) + namespace { std::unique_ptr g_sample; HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; -}; +} bool g_HDRMode = false; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void SetDisplayMode() noexcept; +void ExitSample() noexcept; // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) @@ -58,6 +67,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp // Register class and create window PAPPSTATE_REGISTRATION hPLM = {}; + PAPPCONSTRAIN_REGISTRATION hPLM2 = {}; + { // Register class WNDCLASSEXA wcex = {}; @@ -79,6 +90,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp ShowWindow(hwnd, nCmdShow); + SetDisplayMode(); + SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(g_sample.get())); // Sample Usage Telemetry @@ -104,7 +117,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -112,6 +125,13 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp } }, hwnd, &hPLM)) return 1; + + if (RegisterAppConstrainedChangeNotification([](BOOLEAN constrained, PVOID context) + { + // To ensure we use the main UI thread to process the notification, we self-post a message + SendMessage(reinterpret_cast(context), WM_USER + 1, (constrained) ? 1u : 0u, 0); + }, hwnd, &hPLM2)) + return 1; } // Main message loop @@ -132,7 +152,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp g_sample.reset(); UnregisterAppStateChangeNotification(hPLM); - + UnregisterAppConstrainedChangeNotification(hPLM2); + CloseHandle(g_plmSuspendComplete); CloseHandle(g_plmSignalResume); @@ -156,16 +177,50 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); + + SetDisplayMode(); sample->OnResuming(); } break; + + case WM_USER + 1: + if (sample) + { + if (wParam) + { + sample->OnConstrained(); + } + else + { + SetDisplayMode(); + + sample->OnUnConstrained(); + } + } + break; } return DefWindowProc(hWnd, message, wParam, lParam); } +// HDR helper +void SetDisplayMode() noexcept +{ + if (g_sample && g_sample->RequestHDRMode()) + { + // Request HDR mode. + auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); + + g_HDRMode = (result == XDisplayHdrModeResult::Enabled); + +#ifdef _DEBUG + OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); +#endif + } +} + // Exit helper void ExitSample() noexcept { diff --git a/Samples/Graphics/Antialiasing/Readme.docx b/Samples/Graphics/Antialiasing/Readme.docx index 78a58d1..14593ba 100644 Binary files a/Samples/Graphics/Antialiasing/Readme.docx and b/Samples/Graphics/Antialiasing/Readme.docx differ diff --git a/Samples/Graphics/Antialiasing/StepTimer.h b/Samples/Graphics/Antialiasing/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/Antialiasing/StepTimer.h +++ b/Samples/Graphics/Antialiasing/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/Antialiasing/pch.h b/Samples/Graphics/Antialiasing/pch.h index 13bfd59..7b9841f 100644 --- a/Samples/Graphics/Antialiasing/pch.h +++ b/Samples/Graphics/Antialiasing/pch.h @@ -37,8 +37,8 @@ #include -#if _GXDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GXDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -56,15 +56,23 @@ #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include +#include +#include +#include -#include -#include #include + #include #include diff --git a/Samples/Graphics/ComputeParticles/ComputeParticles.cpp b/Samples/Graphics/ComputeParticles/ComputeParticles.cpp index 1290d33..3cc2de9 100644 --- a/Samples/Graphics/ComputeParticles/ComputeParticles.cpp +++ b/Samples/Graphics/ComputeParticles/ComputeParticles.cpp @@ -10,7 +10,7 @@ #include "ATGColors.h" -extern void ExitSample(); +extern void ExitSample() noexcept; using namespace DirectX; using namespace DirectX::SimpleMath; @@ -63,7 +63,7 @@ void Sample::Initialize(HWND window) m_deviceResources->SetWindow(window); - m_deviceResources->CreateDeviceResources(); + m_deviceResources->CreateDeviceResources(); CreateDeviceDependentResources(); m_deviceResources->CreateWindowSizeDependentResources(); @@ -76,6 +76,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); @@ -250,16 +252,16 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -292,8 +294,6 @@ void Sample::CreateDeviceDependentResources() m_commonStates = std::make_unique(device); m_srvPile = std::make_unique(device, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 128, SRV_Count); @@ -329,8 +329,8 @@ void Sample::CreateDeviceDependentResources() m_particles.GenerateGeometry(*m_models[0]); // HUD - auto backBufferRts = RenderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); - auto spritePSD = SpriteBatchPipelineStateDescription(backBufferRts, &CommonStates::AlphaBlend); + const RenderTargetState backBufferRts(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const SpriteBatchPipelineStateDescription spritePSD(backBufferRts, &CommonStates::AlphaBlend); m_hudBatch = std::make_unique(device, resourceUpload, spritePSD); auto finished = resourceUpload.End(m_deviceResources->GetCommandQueue()); @@ -339,7 +339,7 @@ void Sample::CreateDeviceDependentResources() // Instantiate objects from basic scene definition. auto effectFactory = EffectFactory(m_srvPile->Heap(), m_commonStates->Heap()); - auto objectRTState = RenderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState objectRTState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); auto objectPSD = EffectPipelineStateDescription( nullptr, CommonStates::Opaque, diff --git a/Samples/Graphics/ComputeParticles/ComputeParticles.h b/Samples/Graphics/ComputeParticles/ComputeParticles.h index 37aa4a7..38f67e6 100644 --- a/Samples/Graphics/ComputeParticles/ComputeParticles.h +++ b/Samples/Graphics/ComputeParticles/ComputeParticles.h @@ -21,6 +21,12 @@ public: Sample() noexcept(false); ~Sample(); + Sample(Sample&&) = default; + Sample& operator= (Sample&&) = default; + + Sample(Sample const&) = delete; + Sample& operator= (Sample const&) = delete; + // Initialization and management void Initialize(HWND window); @@ -30,9 +36,11 @@ public: // Messages void OnSuspending(); void OnResuming(); + void OnConstrained() {} + void OnUnConstrained() {} // Properties - bool RequestHDRMode() const { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } + bool RequestHDRMode() const noexcept { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } private: void Update(DX::StepTimer const& timer); diff --git a/Samples/Graphics/ComputeParticles/DeviceResources.cpp b/Samples/Graphics/ComputeParticles/DeviceResources.cpp index d76fd63..fa67816 100644 --- a/Samples/Graphics/ComputeParticles/DeviceResources.cpp +++ b/Samples/Graphics/ComputeParticles/DeviceResources.cpp @@ -31,14 +31,13 @@ DeviceResources::DeviceResources( m_rtvDescriptorSize(0), m_screenViewport{}, m_scissorRect{}, - m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_backBufferFormat(backBufferFormat), m_depthBufferFormat(depthBufferFormat), m_backBufferCount(backBufferCount), m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), m_outputSize{0, 0, 1920, 1080}, - m_options(flags), - m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) + m_options(flags) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) { @@ -55,12 +54,16 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } } // Configures the Direct3D device, and stores handles to it and the device context. +#ifdef _GAMING_XBOX_SCARLETT +void DeviceResources::CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags) +#else void DeviceResources::CreateDeviceResources() +#endif { // Create the DX12 API device object. D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; @@ -77,6 +80,17 @@ void DeviceResources::CreateDeviceResources() params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#ifdef _GAMING_XBOX_SCARLETT + params.CreateDeviceFlags = createDeviceFlags; + +#if (_GXDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif +#endif HRESULT hr = D3D12XboxCreateDevice( nullptr, @@ -107,7 +121,7 @@ void DeviceResources::CreateDeviceResources() // Create descriptor heaps for render target views and depth stencil views. D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; - rtvDescriptorHeapDesc.NumDescriptors = (m_options & c_EnableHDR) ? (m_backBufferCount * 2) : m_backBufferCount; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); @@ -152,31 +166,46 @@ void DeviceResources::CreateDeviceResources() m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { - throw std::exception("CreateEvent"); + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } - if (m_options & c_Enable4K_UHD) + if (m_options & (c_Enable4K_UHD | c_EnableQHD)) { switch (XSystemGetDeviceType()) { case XSystemDeviceType::XboxOne: case XSystemDeviceType::XboxOneS: - case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: - m_options &= ~c_Enable4K_UHD; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080)\n"); -#endif + m_options &= ~(c_Enable4K_UHD | c_EnableQHD); break; + case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: + m_options &= ~c_Enable4K_UHD; + if (m_options & c_EnableQHD) + { + m_outputSize = { 0, 0, 2560, 1440 }; + } + break; + + case XSystemDeviceType::XboxScarlettAnaconda /* Xbox Series X */: + case XSystemDeviceType::XboxOneXDevkit: + case XSystemDeviceType::XboxScarlettDevkit: default: - m_outputSize = { 0, 0, 3840, 2160 }; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160)\n"); -#endif + m_outputSize = (m_options & c_Enable4K_UHD) ? RECT{ 0, 0, 3840, 2160 } : RECT{ 0, 0, 2560, 1440 }; break; } } +#ifdef _DEBUG + const char* info = nullptr; + switch (m_outputSize.bottom) + { + case 2160: info = "INFO: Swapchain using 4k (3840 x 2160)\n"; break; + case 1440: info = "INFO: Swapchain using 1440p (2560 x 1440)\n"; break; + default: info = "INFO: Swapchain using 1080p (1920 x 1080)\n"; break; + } + OutputDebugStringA(info); +#endif + RegisterFrameEvents(); } @@ -185,7 +214,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { if (!m_window) { - throw std::exception("Call SetWindow with a valid window handle"); + throw std::logic_error("Call SetWindow with a valid Win32 window handle"); } // Wait until all previous GPU work is complete. @@ -198,7 +227,6 @@ void DeviceResources::CreateWindowSizeDependentResources() for (UINT n = 0; n < m_backBufferCount; n++) { m_renderTargets[n].Reset(); - m_renderTargetsGameDVR[n].Reset(); m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; } @@ -208,7 +236,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -219,6 +247,13 @@ void DeviceResources::CreateWindowSizeDependentResources() ); swapChainBufferDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; +#ifdef _GAMING_XBOX_XBOXONE + if (m_options & c_EnableHDR) + { + swapChainBufferDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_AUTOMATIC_GAMEDVR_TONE_MAP; + } +#endif + D3D12_CLEAR_VALUE swapChainOptimizedClearValue = {}; swapChainOptimizedClearValue.Format = m_backBufferFormat; @@ -240,41 +275,12 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); } - if (m_options & c_EnableHDR) - { - swapChainBufferDesc.Format = swapChainOptimizedClearValue.Format = m_gameDVRFormat; - - for (UINT n = 0; n < m_backBufferCount; n++) - { - ThrowIfFailed(m_d3dDevice->CreateCommittedResource( - &swapChainHeapProperties, - D3D12_HEAP_FLAG_ALLOW_DISPLAY, - &swapChainBufferDesc, - D3D12_RESOURCE_STATE_PRESENT, - &swapChainOptimizedClearValue, - IID_GRAPHICS_PPV_ARGS(m_renderTargetsGameDVR[n].GetAddressOf()))); - - wchar_t name[25] = {}; - swprintf_s(name, L"GameDVR Render target %u", n); - m_renderTargetsGameDVR[n]->SetName(name); - - D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; - rtvDesc.Format = m_gameDVRFormat; - rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + n), m_rtvDescriptorSize); - m_d3dDevice->CreateRenderTargetView(m_renderTargetsGameDVR[n].Get(), &rtvDesc, rtvDescriptorGameDVR); - } - } - // Reset the index to the current back buffer. m_backBufferIndex = 0; @@ -282,7 +288,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -295,7 +301,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -331,10 +337,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -342,23 +344,10 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), - beforeState, afterState), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, afterState); + m_commandList->ResourceBarrier(1, &barrier); } } @@ -368,20 +357,10 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); } // Send the command list off to the GPU for processing. @@ -389,32 +368,24 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); // Present the backbuffer using the PresentX API. - D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters[2] = {}; - planeParameters[0].Token = planeParameters[1].Token = m_framePipelineToken; - planeParameters[0].ResourceCount = planeParameters[1].ResourceCount = 1; - planeParameters[0].ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); + D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters = {}; + planeParameters.Token = m_framePipelineToken; + planeParameters.ResourceCount = 1; + planeParameters.ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); if (m_options & c_EnableHDR) { - planeParameters[0].pSrcViewRects = planeParameters[1].pSrcViewRects = &m_outputSize; - planeParameters[0].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; - planeParameters[1].ppResources = m_renderTargetsGameDVR[m_backBufferIndex].GetAddressOf(); - planeParameters[1].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; - - ThrowIfFailed( - m_commandQueue->PresentX(2, planeParameters, params) - ); - } - else - { - ThrowIfFailed( - m_commandQueue->PresentX(1, planeParameters, params) - ); + planeParameters.ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; } - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + ThrowIfFailed( + m_commandQueue->PresentX(1, &planeParameters, params) + ); - MoveToNextFrame(); + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -436,13 +407,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -451,25 +422,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/Graphics/ComputeParticles/DeviceResources.h b/Samples/Graphics/ComputeParticles/DeviceResources.h index 1d26b17..4924894 100644 --- a/Samples/Graphics/ComputeParticles/DeviceResources.h +++ b/Samples/Graphics/ComputeParticles/DeviceResources.h @@ -10,8 +10,11 @@ namespace DX class DeviceResources { public: - static constexpr unsigned int c_Enable4K_UHD = 0x1; - static constexpr unsigned int c_EnableHDR = 0x2; + static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_ReverseDepth = 0x8; + static constexpr unsigned int c_AmplificationShaders = 0x10; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -25,7 +28,11 @@ namespace DX DeviceResources(DeviceResources const&) = delete; DeviceResources& operator= (DeviceResources const&) = delete; +#ifdef _GAMING_XBOX_SCARLETT + void CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags = D3D12XBOX_CREATE_DEVICE_FLAG_NONE); +#else void CreateDeviceResources(); +#endif void CreateWindowSizeDependentResources(); void SetWindow(HWND window) noexcept { m_window = window; } void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT, @@ -35,6 +42,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -67,19 +75,7 @@ namespace DX return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); } - // Direct3D HDR Game DVR support for Xbox One. - ID3D12Resource* GetGameDVRRenderTarget() const noexcept { return m_renderTargetsGameDVR[m_backBufferIndex].Get(); } - DXGI_FORMAT GetGameDVRFormat() const noexcept { return m_gameDVRFormat; } - - CD3DX12_CPU_DESCRIPTOR_HANDLE GetGameDVRRenderTargetView() const noexcept - { - return CD3DX12_CPU_DESCRIPTOR_HANDLE( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + m_backBufferIndex), m_rtvDescriptorSize); - } - private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; @@ -126,9 +122,5 @@ namespace DX // DeviceResources options (see flags above) unsigned int m_options; - - // Direct3D HDR Game DVR support for Xbox One. - Microsoft::WRL::ComPtr m_renderTargetsGameDVR[MAX_BACK_BUFFER_COUNT]; - DXGI_FORMAT m_gameDVRFormat; }; } diff --git a/Samples/Graphics/ComputeParticles/Main.cpp b/Samples/Graphics/ComputeParticles/Main.cpp index 6f6c0c2..1fdf8c0 100644 --- a/Samples/Graphics/ComputeParticles/Main.cpp +++ b/Samples/Graphics/ComputeParticles/Main.cpp @@ -1,7 +1,7 @@ //-------------------------------------------------------------------------------------- // Main.cpp // -// Entry point for Microsoft GDK with Xbox extensions. +// Entry point for Microsoft GDK with Xbox extensions // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. @@ -18,16 +18,25 @@ using namespace DirectX; +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +#pragma warning(disable : 4061) + namespace { std::unique_ptr g_sample; HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; -}; +} bool g_HDRMode = false; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void SetDisplayMode() noexcept; +void ExitSample() noexcept; // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) @@ -58,6 +67,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp // Register class and create window PAPPSTATE_REGISTRATION hPLM = {}; + PAPPCONSTRAIN_REGISTRATION hPLM2 = {}; + { // Register class WNDCLASSEXA wcex = {}; @@ -66,7 +77,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.lpszClassName = u8"ComputeParticlesWindowClass"; - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); if (!RegisterClassExA(&wcex)) return 1; @@ -79,17 +90,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp ShowWindow(hwnd, nCmdShow); - if (g_sample->RequestHDRMode()) - { - // Request HDR mode. - auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); - - g_HDRMode = (result == XDisplayHdrModeResult::Enabled); - - #ifdef _DEBUG - OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); - #endif - } + SetDisplayMode(); SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(g_sample.get())); @@ -116,7 +117,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -124,6 +125,13 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp } }, hwnd, &hPLM)) return 1; + + if (RegisterAppConstrainedChangeNotification([](BOOLEAN constrained, PVOID context) + { + // To ensure we use the main UI thread to process the notification, we self-post a message + SendMessage(reinterpret_cast(context), WM_USER + 1, (constrained) ? 1u : 0u, 0); + }, hwnd, &hPLM2)) + return 1; } // Main message loop @@ -144,13 +152,14 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp g_sample.reset(); UnregisterAppStateChangeNotification(hPLM); - + UnregisterAppConstrainedChangeNotification(hPLM2); + CloseHandle(g_plmSuspendComplete); CloseHandle(g_plmSignalResume); XGameRuntimeUninitialize(); - return (int) msg.wParam; + return static_cast(msg.wParam); } // Windows procedure @@ -168,18 +177,52 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); + + SetDisplayMode(); sample->OnResuming(); } break; + + case WM_USER + 1: + if (sample) + { + if (wParam) + { + sample->OnConstrained(); + } + else + { + SetDisplayMode(); + + sample->OnUnConstrained(); + } + } + break; } return DefWindowProc(hWnd, message, wParam, lParam); } +// HDR helper +void SetDisplayMode() noexcept +{ + if (g_sample && g_sample->RequestHDRMode()) + { + // Request HDR mode. + auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); + + g_HDRMode = (result == XDisplayHdrModeResult::Enabled); + +#ifdef _DEBUG + OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); +#endif + } +} + // Exit helper -void ExitSample() +void ExitSample() noexcept { PostQuitMessage(0); } diff --git a/Samples/Graphics/ComputeParticles/StepTimer.h b/Samples/Graphics/ComputeParticles/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/ComputeParticles/StepTimer.h +++ b/Samples/Graphics/ComputeParticles/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/ComputeParticles/pch.h b/Samples/Graphics/ComputeParticles/pch.h index 02f8a02..1dfc644 100644 --- a/Samples/Graphics/ComputeParticles/pch.h +++ b/Samples/Graphics/ComputeParticles/pch.h @@ -37,8 +37,8 @@ #include -#if _GXDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GXDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -56,14 +56,21 @@ #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include +#include +#include +#include -#include -#include #include #include @@ -93,7 +100,7 @@ namespace DX class com_exception : public std::exception { public: - com_exception(HRESULT hr) : result(hr) {} + com_exception(HRESULT hr) noexcept : result(hr) {} const char* what() const override { diff --git a/Samples/Graphics/ComputeParticles/readme.docx b/Samples/Graphics/ComputeParticles/readme.docx index 3d56565..c138422 100644 Binary files a/Samples/Graphics/ComputeParticles/readme.docx and b/Samples/Graphics/ComputeParticles/readme.docx differ diff --git a/Samples/Graphics/DXRTriangle/DXRTriangle/DXRTriangle.cpp b/Samples/Graphics/DXRTriangle/DXRTriangle/DXRTriangle.cpp index 71fc2ab..be16246 100644 --- a/Samples/Graphics/DXRTriangle/DXRTriangle/DXRTriangle.cpp +++ b/Samples/Graphics/DXRTriangle/DXRTriangle/DXRTriangle.cpp @@ -29,7 +29,7 @@ Sample::Sample() noexcept(false) : m_holeSize(0.1f) { // Renders only 2D, so no need for a depth buffer. - m_deviceResources = std::make_unique(DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN, 2); + m_deviceResources = std::make_unique(DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN); m_deviceResources->RegisterDeviceNotify(this); } @@ -50,7 +50,7 @@ void Sample::Initialize(HWND window, int width, int height) m_deviceResources->SetWindow(window, width, height); - m_deviceResources->CreateDeviceResources(); + m_deviceResources->CreateDeviceResources(); CreateDeviceDependentResources(); m_deviceResources->CreateWindowSizeDependentResources(); @@ -63,6 +63,10 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); +#ifdef _GAMING_XBOX + m_deviceResources->WaitForOrigin(); +#endif + m_timer.Tick([&]() { Update(m_timer); @@ -86,7 +90,7 @@ void Sample::Update(DX::StepTimer const& timer) m_keyboardButtons.Update(kb); - const float SPEED_OF_CHANGE = 0.25f; + constexpr float SPEED_OF_CHANGE = 0.25f; if (pad.IsConnected()) { @@ -223,8 +227,8 @@ void Sample::RenderHUD(ID3D12GraphicsCommandList* commandList) commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); - auto size = m_deviceResources->GetOutputSize(); - auto safe = SimpleMath::Viewport::ComputeTitleSafeArea((UINT)size.right, (UINT)size.bottom); + auto const size = m_deviceResources->GetOutputSize(); + auto const safe = SimpleMath::Viewport::ComputeTitleSafeArea((UINT)size.right, (UINT)size.bottom); wchar_t textBuffer[128] = {}; XMFLOAT2 textPos = XMFLOAT2(float(safe.left), float(safe.top)); @@ -265,14 +269,6 @@ void Sample::RenderHUD(ID3D12GraphicsCommandList* commandList) #pragma region Message Handlers // Message handlers -void Sample::OnActivated() -{ -} - -void Sample::OnDeactivated() -{ -} - void Sample::OnSuspending() { m_deviceResources->Suspend(); @@ -288,7 +284,7 @@ void Sample::OnResuming() void Sample::OnWindowMoved() { - auto r = m_deviceResources->GetOutputSize(); + auto const r = m_deviceResources->GetOutputSize(); m_deviceResources->WindowSizeChanged(r.right, r.bottom); } @@ -314,6 +310,11 @@ void Sample::CreateRaytracingPipeline() { auto device = m_deviceResources->GetD3DDevice(); +#if defined(_GAMING_XBOX_SCARLETT) && (_GRDK_VER >= 0x55F00C58 /* GDK Edition 220300 */) + // Save the RtPso PDB on the scratch drive + device->SetCompileTimeShaderPdbPathX(L"D:\\"); +#endif + CD3DX12_STATE_OBJECT_DESC raytracingPipeline{ D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE }; auto raytracingLibrary = raytracingPipeline.CreateSubobject(); @@ -387,10 +388,10 @@ void Sample::BuildBottomLevelAccelerationStructure(bool buildEveryFrame) auto device = m_deviceResources->GetD3DDevice(); auto commandList = m_deviceResources->GetCommandList(); - const UINT vertexCount = 3; - const UINT vertexSize = sizeof(XMFLOAT3); - const UINT indexCount = 3; - const UINT indexSize = sizeof(UINT); + constexpr UINT vertexCount = 3; + constexpr UINT vertexSize = sizeof(XMFLOAT3); + constexpr UINT indexCount = 3; + constexpr UINT indexSize = sizeof(UINT); // Build a BLAS for one triangle... D3D12_RAYTRACING_GEOMETRY_DESC geometryDesc = { D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES, D3D12_RAYTRACING_GEOMETRY_FLAG_NONE, {} }; @@ -556,8 +557,8 @@ void Sample::CreateDeviceDependentResources() resourceUpload.Begin(); // HUD - auto backBufferRts = RenderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); - auto spritePSD = SpriteBatchPipelineStateDescription(backBufferRts, &CommonStates::AlphaBlend); + const RenderTargetState backBufferRts(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const SpriteBatchPipelineStateDescription spritePSD(backBufferRts, &CommonStates::AlphaBlend); m_hudBatch = std::make_unique(device, resourceUpload, spritePSD); wchar_t strFilePath[MAX_PATH] = {}; @@ -583,7 +584,7 @@ void Sample::CreateDeviceDependentResources() void Sample::CreateWindowSizeDependentResources() { auto device = m_deviceResources->GetD3DDevice(); - RECT outputSize = m_deviceResources->GetOutputSize(); + auto const outputSize = m_deviceResources->GetOutputSize(); D3D12_HEAP_PROPERTIES defaultHeapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); diff --git a/Samples/Graphics/DXRTriangle/DXRTriangle/DXRTriangle.h b/Samples/Graphics/DXRTriangle/DXRTriangle/DXRTriangle.h index e2967d3..81d0dd5 100644 --- a/Samples/Graphics/DXRTriangle/DXRTriangle/DXRTriangle.h +++ b/Samples/Graphics/DXRTriangle/DXRTriangle/DXRTriangle.h @@ -13,10 +13,7 @@ struct SimpleTriangleRecord : public ShaderRecord { - SimpleTriangleRecord() : ShaderRecord() - { - - } + SimpleTriangleRecord() = default; SimpleTriangleRecord(ID3D12StateObjectProperties* props, LPCWSTR exportName) { @@ -64,8 +61,8 @@ public: void OnDeviceRestored() override; // Messages - void OnActivated(); - void OnDeactivated(); + void OnActivated() {} + void OnDeactivated() {} void OnSuspending(); void OnResuming(); void OnWindowMoved(); diff --git a/Samples/Graphics/DXRTriangle/DXRTriangle/DXRTriangle.vcxproj b/Samples/Graphics/DXRTriangle/DXRTriangle/DXRTriangle.vcxproj index 471425b..d5d4520 100644 --- a/Samples/Graphics/DXRTriangle/DXRTriangle/DXRTriangle.vcxproj +++ b/Samples/Graphics/DXRTriangle/DXRTriangle/DXRTriangle.vcxproj @@ -438,6 +438,9 @@ + /Qembed_debug %(AdditionalOptions) + /Qembed_debug %(AdditionalOptions) + /Qembed_debug %(AdditionalOptions) diff --git a/Samples/Graphics/DXRTriangle/DXRTriangle/DeviceResources.cpp b/Samples/Graphics/DXRTriangle/DXRTriangle/DeviceResources.cpp index ef5bdf1..7df6750 100644 --- a/Samples/Graphics/DXRTriangle/DXRTriangle/DeviceResources.cpp +++ b/Samples/Graphics/DXRTriangle/DXRTriangle/DeviceResources.cpp @@ -1,7 +1,7 @@ // // DeviceResources.cpp - A wrapper for the Direct3D 12/12.X device and swapchain // -// Modified to use ID3D12Device6/ID3D12GraphicsCommandList5 for DXR access +// Modified to use ID3D12Device8/ID3D12GraphicsCommandList5 for DXR access // #include "pch.h" @@ -12,7 +12,6 @@ using namespace DX; using Microsoft::WRL::ComPtr; -#ifdef _GAMING_DESKTOP #ifdef __clang__ #pragma clang diagnostic ignored "-Wcovered-switch-default" #pragma clang diagnostic ignored "-Wswitch-enum" @@ -20,6 +19,7 @@ using Microsoft::WRL::ComPtr; #pragma warning(disable : 4061) +#ifdef _GAMING_DESKTOP namespace { inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) noexcept @@ -39,7 +39,8 @@ namespace DeviceResources::DeviceResources( DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, - UINT backBufferCount) noexcept(false) : + UINT backBufferCount, + unsigned int flags) noexcept(false) : m_backBufferIndex(0), m_fenceValues{}, #ifdef _GAMING_XBOX @@ -54,6 +55,7 @@ DeviceResources::DeviceResources( m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_0), m_outputSize{ 0, 0, 1, 1 }, + m_options(flags), m_deviceNotify(nullptr) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) @@ -72,7 +74,7 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } #endif } @@ -98,6 +100,14 @@ void DeviceResources::CreateDeviceResources() params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#if defined(_GAMING_XBOX_SCARLETT) && (_GRDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif + HRESULT hr = D3D12XboxCreateDevice( nullptr, ¶ms, @@ -171,7 +181,7 @@ void DeviceResources::CreateDeviceResources() #ifdef _DEBUG if (hr == E_NOINTERFACE) { - OutputDebugStringA("ERROR: Requires Windows 10 (Version 1903, Build 18362) or later\n"); + OutputDebugStringA("ERROR: Requires Windows 10 (Version 2004, Build 19041) or later\n"); } #endif ThrowIfFailed(hr); @@ -326,7 +336,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -358,7 +368,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -369,7 +379,7 @@ void DeviceResources::CreateWindowSizeDependentResources() #else // _GAMING_DESKTOP - DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + const DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); // If the swap chain already exists, resize it, otherwise create one. if (m_swapChain) @@ -452,7 +462,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -467,7 +477,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -480,7 +490,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -591,12 +601,6 @@ void DeviceResources::HandleDeviceLost() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { -#ifdef _GAMING_XBOX - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); -#endif - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -604,7 +608,8 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState); m_commandList->ResourceBarrier(1, &barrier); } @@ -616,7 +621,9 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); m_commandList->ResourceBarrier(1, &barrier); } @@ -636,9 +643,12 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) m_commandQueue->PresentX(1, &planeParameters, nullptr) ); - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. -#else + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + +#else // _GAMING_DESKTOP // The first argument instructs DXGI to block until VSync, putting the application // to sleep until the next VSync. This ensures we don't waste any cycles rendering @@ -661,9 +671,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) ThrowIfFailed(hr); } -#endif - MoveToNextFrame(); +#endif } // Handle GPU suspend/resume @@ -689,13 +698,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -704,32 +713,20 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() -{ - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. #ifdef _GAMING_XBOX - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; -#else - m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); -#endif - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() +{ + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } -#ifdef _GAMING_XBOX // Set frame interval and register for frame events void DeviceResources::RegisterFrameEvents() { @@ -758,7 +755,30 @@ void DeviceResources::RegisterFrameEvents() nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE)); } -#else + +#else // _GAMING_DESKTOP + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + // This method acquires the first available hardware adapter that supports Direct3D 12. // If no such adapter can be found, try WARP. Otherwise throw an exception. void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) diff --git a/Samples/Graphics/DXRTriangle/DXRTriangle/DeviceResources.h b/Samples/Graphics/DXRTriangle/DXRTriangle/DeviceResources.h index d3c3894..f7718ae 100644 --- a/Samples/Graphics/DXRTriangle/DXRTriangle/DeviceResources.h +++ b/Samples/Graphics/DXRTriangle/DXRTriangle/DeviceResources.h @@ -1,7 +1,7 @@ // // DeviceResources.h - A wrapper for the Direct3D 12/12.X device and swapchain // -// Modified to use ID3D12Device6/ID3D12GraphicsCommandList5 for DXR access +// Modified to use ID3D12Device8/ID3D12GraphicsCommandList5 for DXR access // #pragma once @@ -22,9 +22,13 @@ namespace DX class DeviceResources { public: + static constexpr unsigned int c_ReverseDepth = 0x1; + static constexpr unsigned int c_AmplificationShaders = 0x2; + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, - UINT backBufferCount = 2) noexcept(false); + UINT backBufferCount = 2, + unsigned int flags = 0) noexcept(false); ~DeviceResources(); DeviceResources(DeviceResources&&) = default; @@ -45,6 +49,9 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; +#ifdef _GAMING_XBOX + void WaitForOrigin(); +#endif // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -68,6 +75,7 @@ namespace DX D3D12_RECT GetScissorRect() const noexcept { return m_scissorRect; } UINT GetCurrentFrameIndex() const noexcept { return m_backBufferIndex; } UINT GetBackBufferCount() const noexcept { return m_backBufferCount; } + unsigned int GetDeviceOptions() const noexcept { return m_options; } CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const noexcept { @@ -81,10 +89,10 @@ namespace DX } private: - void MoveToNextFrame(); #ifdef _GAMING_XBOX void RegisterFrameEvents(); #else + void MoveToNextFrame(); void GetAdapter(IDXGIAdapter1** ppAdapter); #endif @@ -93,7 +101,7 @@ namespace DX UINT m_backBufferIndex; // Direct3D objects. - Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dDevice; Microsoft::WRL::ComPtr m_commandList; Microsoft::WRL::ComPtr m_commandQueue; Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; @@ -131,6 +139,9 @@ namespace DX D3D_FEATURE_LEVEL m_d3dFeatureLevel; RECT m_outputSize; + // DeviceResources options (see flags above) + unsigned int m_options; + // The IDeviceNotify can be held directly as it owns the DeviceResources. IDeviceNotify* m_deviceNotify; }; diff --git a/Samples/Graphics/DXRTriangle/DXRTriangle/Main.cpp b/Samples/Graphics/DXRTriangle/DXRTriangle/Main.cpp index 7ba6839..1905a93 100644 --- a/Samples/Graphics/DXRTriangle/DXRTriangle/Main.cpp +++ b/Samples/Graphics/DXRTriangle/DXRTriangle/Main.cpp @@ -417,7 +417,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); diff --git a/Samples/Graphics/DXRTriangle/DXRTriangle/StepTimer.h b/Samples/Graphics/DXRTriangle/DXRTriangle/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/DXRTriangle/DXRTriangle/StepTimer.h +++ b/Samples/Graphics/DXRTriangle/DXRTriangle/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/DXRTriangle/DXRTriangle/pch.h b/Samples/Graphics/DXRTriangle/DXRTriangle/pch.h index 038fc6d..cd100f4 100644 --- a/Samples/Graphics/DXRTriangle/DXRTriangle/pch.h +++ b/Samples/Graphics/DXRTriangle/DXRTriangle/pch.h @@ -41,8 +41,8 @@ #include -#if _GRDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GRDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT diff --git a/Samples/Graphics/DeferredParticles/DeferredParticles.cpp b/Samples/Graphics/DeferredParticles/DeferredParticles.cpp index bc6d42e..4bc30b1 100644 --- a/Samples/Graphics/DeferredParticles/DeferredParticles.cpp +++ b/Samples/Graphics/DeferredParticles/DeferredParticles.cpp @@ -10,10 +10,7 @@ #include "pch.h" #include "DeferredParticles.h" -// C4238: nonstandard extension used: class rvalue used as lvalue -#pragma warning(disable : 4238) - -extern void ExitSample(); +extern void ExitSample() noexcept; using namespace DirectX; @@ -98,7 +95,12 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); - m_timer.Tick([&]() { Update(m_timer); }); + m_deviceResources->WaitForOrigin(); + + m_timer.Tick([&]() + { + Update(m_timer); + }); Render(); @@ -196,7 +198,7 @@ void Sample::Render() } // Restore the viewport, as the sky changed the min depth bounds. - auto vp = m_deviceResources->GetScreenViewport(); + auto const vp = m_deviceResources->GetScreenViewport(); commandList->RSSetViewports(1, &vp); // Render the particle systems. @@ -206,7 +208,7 @@ void Sample::Render() { ScopedPixEvent hud(commandList, PIX_COLOR_DEFAULT, L"HUD"); - auto safe = DirectX::SimpleMath::Viewport::ComputeTitleSafeArea(UINT(m_displayWidth), UINT(m_displayHeight)); + auto const safe = DirectX::SimpleMath::Viewport::ComputeTitleSafeArea(UINT(m_displayWidth), UINT(m_displayHeight)); wchar_t textBuffer[1024] = {}; XMFLOAT2 textPos = XMFLOAT2(float(safe.left), float(safe.top)); @@ -247,16 +249,16 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -289,8 +291,6 @@ void Sample::CreateDeviceDependentResources() m_commonStates = std::make_unique(device); m_srvPile = std::make_unique(device, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 128, SRV_Count); @@ -305,8 +305,8 @@ void Sample::CreateDeviceDependentResources() resourceUpload.Begin(); // HUD - auto backBufferRts = RenderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); - auto spritePSD = SpriteBatchPipelineStateDescription(backBufferRts, &CommonStates::AlphaBlend); + const RenderTargetState backBufferRts(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const SpriteBatchPipelineStateDescription spritePSD(backBufferRts, &CommonStates::AlphaBlend); m_hudBatch = std::make_unique(device, resourceUpload, spritePSD); m_particleWorld.CreateDeviceDependentResources(m_deviceResources.get(), resourceUpload, *m_models[0].get()); @@ -399,7 +399,7 @@ void Sample::CreateDeviceDependentResources() void Sample::CreateWindowSizeDependentResources() { auto device = m_deviceResources->GetD3DDevice(); - const auto size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); // Calculate display dimensions. m_displayWidth = size.right - size.left; @@ -468,7 +468,7 @@ void Sample::SetupPipelineSky(ID3D12GraphicsCommandList* commandList, const Mode SetupPipelineCommon(commandList, part, instIndex, texOffset, skyView); - D3D12_VIEWPORT vpSky = m_deviceResources->GetScreenViewport(); + auto vpSky = m_deviceResources->GetScreenViewport(); vpSky.MinDepth = 0.999f; commandList->RSSetViewports(1, &vpSky); commandList->SetPipelineState(m_skyPSO.Get()); diff --git a/Samples/Graphics/DeferredParticles/DeferredParticles.h b/Samples/Graphics/DeferredParticles/DeferredParticles.h index fe666de..632f976 100644 --- a/Samples/Graphics/DeferredParticles/DeferredParticles.h +++ b/Samples/Graphics/DeferredParticles/DeferredParticles.h @@ -20,18 +20,26 @@ public: Sample() noexcept(false); ~Sample(); + Sample(Sample&&) = default; + Sample& operator= (Sample&&) = default; + + Sample(Sample const&) = delete; + Sample& operator= (Sample const&) = delete; + // Initialization and management void Initialize(HWND window); - // Basic Sample loop + // Basic render loop void Tick(); // Messages void OnSuspending(); void OnResuming(); + void OnConstrained() {} + void OnUnConstrained() {} // Properties - bool RequestHDRMode() const { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } + bool RequestHDRMode() const noexcept { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } // Helper callback functions that setup the pipeline state for the scene & sky mesh types. void SetupPipelineScene(ID3D12GraphicsCommandList* commandList, const DirectX::ModelMeshPart& part, int instIndex, int texOffset); diff --git a/Samples/Graphics/DeferredParticles/DeviceResources.cpp b/Samples/Graphics/DeferredParticles/DeviceResources.cpp index d76fd63..fa67816 100644 --- a/Samples/Graphics/DeferredParticles/DeviceResources.cpp +++ b/Samples/Graphics/DeferredParticles/DeviceResources.cpp @@ -31,14 +31,13 @@ DeviceResources::DeviceResources( m_rtvDescriptorSize(0), m_screenViewport{}, m_scissorRect{}, - m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_backBufferFormat(backBufferFormat), m_depthBufferFormat(depthBufferFormat), m_backBufferCount(backBufferCount), m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), m_outputSize{0, 0, 1920, 1080}, - m_options(flags), - m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) + m_options(flags) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) { @@ -55,12 +54,16 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } } // Configures the Direct3D device, and stores handles to it and the device context. +#ifdef _GAMING_XBOX_SCARLETT +void DeviceResources::CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags) +#else void DeviceResources::CreateDeviceResources() +#endif { // Create the DX12 API device object. D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; @@ -77,6 +80,17 @@ void DeviceResources::CreateDeviceResources() params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#ifdef _GAMING_XBOX_SCARLETT + params.CreateDeviceFlags = createDeviceFlags; + +#if (_GXDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif +#endif HRESULT hr = D3D12XboxCreateDevice( nullptr, @@ -107,7 +121,7 @@ void DeviceResources::CreateDeviceResources() // Create descriptor heaps for render target views and depth stencil views. D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; - rtvDescriptorHeapDesc.NumDescriptors = (m_options & c_EnableHDR) ? (m_backBufferCount * 2) : m_backBufferCount; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); @@ -152,31 +166,46 @@ void DeviceResources::CreateDeviceResources() m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { - throw std::exception("CreateEvent"); + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } - if (m_options & c_Enable4K_UHD) + if (m_options & (c_Enable4K_UHD | c_EnableQHD)) { switch (XSystemGetDeviceType()) { case XSystemDeviceType::XboxOne: case XSystemDeviceType::XboxOneS: - case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: - m_options &= ~c_Enable4K_UHD; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080)\n"); -#endif + m_options &= ~(c_Enable4K_UHD | c_EnableQHD); break; + case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: + m_options &= ~c_Enable4K_UHD; + if (m_options & c_EnableQHD) + { + m_outputSize = { 0, 0, 2560, 1440 }; + } + break; + + case XSystemDeviceType::XboxScarlettAnaconda /* Xbox Series X */: + case XSystemDeviceType::XboxOneXDevkit: + case XSystemDeviceType::XboxScarlettDevkit: default: - m_outputSize = { 0, 0, 3840, 2160 }; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160)\n"); -#endif + m_outputSize = (m_options & c_Enable4K_UHD) ? RECT{ 0, 0, 3840, 2160 } : RECT{ 0, 0, 2560, 1440 }; break; } } +#ifdef _DEBUG + const char* info = nullptr; + switch (m_outputSize.bottom) + { + case 2160: info = "INFO: Swapchain using 4k (3840 x 2160)\n"; break; + case 1440: info = "INFO: Swapchain using 1440p (2560 x 1440)\n"; break; + default: info = "INFO: Swapchain using 1080p (1920 x 1080)\n"; break; + } + OutputDebugStringA(info); +#endif + RegisterFrameEvents(); } @@ -185,7 +214,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { if (!m_window) { - throw std::exception("Call SetWindow with a valid window handle"); + throw std::logic_error("Call SetWindow with a valid Win32 window handle"); } // Wait until all previous GPU work is complete. @@ -198,7 +227,6 @@ void DeviceResources::CreateWindowSizeDependentResources() for (UINT n = 0; n < m_backBufferCount; n++) { m_renderTargets[n].Reset(); - m_renderTargetsGameDVR[n].Reset(); m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; } @@ -208,7 +236,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -219,6 +247,13 @@ void DeviceResources::CreateWindowSizeDependentResources() ); swapChainBufferDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; +#ifdef _GAMING_XBOX_XBOXONE + if (m_options & c_EnableHDR) + { + swapChainBufferDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_AUTOMATIC_GAMEDVR_TONE_MAP; + } +#endif + D3D12_CLEAR_VALUE swapChainOptimizedClearValue = {}; swapChainOptimizedClearValue.Format = m_backBufferFormat; @@ -240,41 +275,12 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); } - if (m_options & c_EnableHDR) - { - swapChainBufferDesc.Format = swapChainOptimizedClearValue.Format = m_gameDVRFormat; - - for (UINT n = 0; n < m_backBufferCount; n++) - { - ThrowIfFailed(m_d3dDevice->CreateCommittedResource( - &swapChainHeapProperties, - D3D12_HEAP_FLAG_ALLOW_DISPLAY, - &swapChainBufferDesc, - D3D12_RESOURCE_STATE_PRESENT, - &swapChainOptimizedClearValue, - IID_GRAPHICS_PPV_ARGS(m_renderTargetsGameDVR[n].GetAddressOf()))); - - wchar_t name[25] = {}; - swprintf_s(name, L"GameDVR Render target %u", n); - m_renderTargetsGameDVR[n]->SetName(name); - - D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; - rtvDesc.Format = m_gameDVRFormat; - rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + n), m_rtvDescriptorSize); - m_d3dDevice->CreateRenderTargetView(m_renderTargetsGameDVR[n].Get(), &rtvDesc, rtvDescriptorGameDVR); - } - } - // Reset the index to the current back buffer. m_backBufferIndex = 0; @@ -282,7 +288,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -295,7 +301,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -331,10 +337,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -342,23 +344,10 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), - beforeState, afterState), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, afterState); + m_commandList->ResourceBarrier(1, &barrier); } } @@ -368,20 +357,10 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); } // Send the command list off to the GPU for processing. @@ -389,32 +368,24 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); // Present the backbuffer using the PresentX API. - D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters[2] = {}; - planeParameters[0].Token = planeParameters[1].Token = m_framePipelineToken; - planeParameters[0].ResourceCount = planeParameters[1].ResourceCount = 1; - planeParameters[0].ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); + D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters = {}; + planeParameters.Token = m_framePipelineToken; + planeParameters.ResourceCount = 1; + planeParameters.ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); if (m_options & c_EnableHDR) { - planeParameters[0].pSrcViewRects = planeParameters[1].pSrcViewRects = &m_outputSize; - planeParameters[0].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; - planeParameters[1].ppResources = m_renderTargetsGameDVR[m_backBufferIndex].GetAddressOf(); - planeParameters[1].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; - - ThrowIfFailed( - m_commandQueue->PresentX(2, planeParameters, params) - ); - } - else - { - ThrowIfFailed( - m_commandQueue->PresentX(1, planeParameters, params) - ); + planeParameters.ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; } - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + ThrowIfFailed( + m_commandQueue->PresentX(1, &planeParameters, params) + ); - MoveToNextFrame(); + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -436,13 +407,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -451,25 +422,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/Graphics/DeferredParticles/DeviceResources.h b/Samples/Graphics/DeferredParticles/DeviceResources.h index 1d26b17..4924894 100644 --- a/Samples/Graphics/DeferredParticles/DeviceResources.h +++ b/Samples/Graphics/DeferredParticles/DeviceResources.h @@ -10,8 +10,11 @@ namespace DX class DeviceResources { public: - static constexpr unsigned int c_Enable4K_UHD = 0x1; - static constexpr unsigned int c_EnableHDR = 0x2; + static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_ReverseDepth = 0x8; + static constexpr unsigned int c_AmplificationShaders = 0x10; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -25,7 +28,11 @@ namespace DX DeviceResources(DeviceResources const&) = delete; DeviceResources& operator= (DeviceResources const&) = delete; +#ifdef _GAMING_XBOX_SCARLETT + void CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags = D3D12XBOX_CREATE_DEVICE_FLAG_NONE); +#else void CreateDeviceResources(); +#endif void CreateWindowSizeDependentResources(); void SetWindow(HWND window) noexcept { m_window = window; } void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT, @@ -35,6 +42,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -67,19 +75,7 @@ namespace DX return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); } - // Direct3D HDR Game DVR support for Xbox One. - ID3D12Resource* GetGameDVRRenderTarget() const noexcept { return m_renderTargetsGameDVR[m_backBufferIndex].Get(); } - DXGI_FORMAT GetGameDVRFormat() const noexcept { return m_gameDVRFormat; } - - CD3DX12_CPU_DESCRIPTOR_HANDLE GetGameDVRRenderTargetView() const noexcept - { - return CD3DX12_CPU_DESCRIPTOR_HANDLE( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + m_backBufferIndex), m_rtvDescriptorSize); - } - private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; @@ -126,9 +122,5 @@ namespace DX // DeviceResources options (see flags above) unsigned int m_options; - - // Direct3D HDR Game DVR support for Xbox One. - Microsoft::WRL::ComPtr m_renderTargetsGameDVR[MAX_BACK_BUFFER_COUNT]; - DXGI_FORMAT m_gameDVRFormat; }; } diff --git a/Samples/Graphics/DeferredParticles/Main.cpp b/Samples/Graphics/DeferredParticles/Main.cpp index 19c385d..b7c0677 100644 --- a/Samples/Graphics/DeferredParticles/Main.cpp +++ b/Samples/Graphics/DeferredParticles/Main.cpp @@ -1,7 +1,7 @@ //-------------------------------------------------------------------------------------- // Main.cpp // -// Entry point for Microsoft GDK with Xbox extensions. +// Entry point for Microsoft GDK with Xbox extensions // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. @@ -18,16 +18,25 @@ using namespace DirectX; +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +#pragma warning(disable : 4061) + namespace { std::unique_ptr g_sample; HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; -}; +} bool g_HDRMode = false; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void SetDisplayMode() noexcept; +void ExitSample() noexcept; // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) @@ -58,6 +67,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp // Register class and create window PAPPSTATE_REGISTRATION hPLM = {}; + PAPPCONSTRAIN_REGISTRATION hPLM2 = {}; + { // Register class WNDCLASSEXA wcex = {}; @@ -66,7 +77,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.lpszClassName = u8"DeferredParticlesWindowClass"; - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); if (!RegisterClassExA(&wcex)) return 1; @@ -79,17 +90,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp ShowWindow(hwnd, nCmdShow); - if (g_sample->RequestHDRMode()) - { - // Request HDR mode. - auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); - - g_HDRMode = (result == XDisplayHdrModeResult::Enabled); - - #ifdef _DEBUG - OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); - #endif - } + SetDisplayMode(); SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(g_sample.get())); @@ -116,7 +117,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -124,6 +125,13 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp } }, hwnd, &hPLM)) return 1; + + if (RegisterAppConstrainedChangeNotification([](BOOLEAN constrained, PVOID context) + { + // To ensure we use the main UI thread to process the notification, we self-post a message + SendMessage(reinterpret_cast(context), WM_USER + 1, (constrained) ? 1u : 0u, 0); + }, hwnd, &hPLM2)) + return 1; } // Main message loop @@ -144,13 +152,14 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp g_sample.reset(); UnregisterAppStateChangeNotification(hPLM); - + UnregisterAppConstrainedChangeNotification(hPLM2); + CloseHandle(g_plmSuspendComplete); CloseHandle(g_plmSignalResume); XGameRuntimeUninitialize(); - return (int) msg.wParam; + return static_cast(msg.wParam); } // Windows procedure @@ -168,18 +177,52 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); + + SetDisplayMode(); sample->OnResuming(); } break; + + case WM_USER + 1: + if (sample) + { + if (wParam) + { + sample->OnConstrained(); + } + else + { + SetDisplayMode(); + + sample->OnUnConstrained(); + } + } + break; } return DefWindowProc(hWnd, message, wParam, lParam); } +// HDR helper +void SetDisplayMode() noexcept +{ + if (g_sample && g_sample->RequestHDRMode()) + { + // Request HDR mode. + auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); + + g_HDRMode = (result == XDisplayHdrModeResult::Enabled); + +#ifdef _DEBUG + OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); +#endif + } +} + // Exit helper -void ExitSample() +void ExitSample() noexcept { PostQuitMessage(0); } diff --git a/Samples/Graphics/DeferredParticles/StepTimer.h b/Samples/Graphics/DeferredParticles/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/DeferredParticles/StepTimer.h +++ b/Samples/Graphics/DeferredParticles/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/DeferredParticles/pch.h b/Samples/Graphics/DeferredParticles/pch.h index 5e20ee5..5da7101 100644 --- a/Samples/Graphics/DeferredParticles/pch.h +++ b/Samples/Graphics/DeferredParticles/pch.h @@ -37,8 +37,8 @@ #include -#if _GXDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GXDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -56,14 +56,21 @@ #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include +#include +#include +#include -#include -#include #include #include @@ -94,7 +101,7 @@ namespace DX class com_exception : public std::exception { public: - com_exception(HRESULT hr) : result(hr) {} + com_exception(HRESULT hr) noexcept : result(hr) {} const char* what() const override { diff --git a/Samples/Graphics/DynamicLOD/DeviceResources.cpp b/Samples/Graphics/DynamicLOD/DeviceResources.cpp index 7d88350..acc2c8a 100644 --- a/Samples/Graphics/DynamicLOD/DeviceResources.cpp +++ b/Samples/Graphics/DynamicLOD/DeviceResources.cpp @@ -12,7 +12,6 @@ using namespace DX; using Microsoft::WRL::ComPtr; -#ifdef _GAMING_DESKTOP #ifdef __clang__ #pragma clang diagnostic ignored "-Wcovered-switch-default" #pragma clang diagnostic ignored "-Wswitch-enum" @@ -20,6 +19,7 @@ using Microsoft::WRL::ComPtr; #pragma warning(disable : 4061) +#ifdef _GAMING_DESKTOP namespace { inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) noexcept @@ -39,7 +39,8 @@ namespace DeviceResources::DeviceResources( DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, - UINT backBufferCount) noexcept(false) : + UINT backBufferCount, + unsigned int flags) noexcept(false) : m_backBufferIndex(0), m_fenceValues{}, #ifdef _GAMING_XBOX @@ -54,6 +55,7 @@ DeviceResources::DeviceResources( m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_0), m_outputSize{ 0, 0, 1, 1 }, + m_options(flags), m_deviceNotify(nullptr) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) @@ -72,7 +74,7 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } #endif } @@ -98,6 +100,14 @@ void DeviceResources::CreateDeviceResources() params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#if defined(_GAMING_XBOX_SCARLETT) && (_GRDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif + HRESULT hr = D3D12XboxCreateDevice( nullptr, ¶ms, @@ -150,7 +160,7 @@ void DeviceResources::CreateDeviceResources() 80 /* IDXGISwapChain::GetContainingOutput: The swapchain's adapter does not control the output on which the swapchain's window resides. */, }; DXGI_INFO_QUEUE_FILTER filter = {}; - filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.NumIDs = static_cast(std::size(hide)); filter.DenyList.pIDList = hide; dxgiInfoQueue->AddStorageFilterEntries(DXGI_DEBUG_DXGI, &filter); } @@ -196,7 +206,7 @@ void DeviceResources::CreateDeviceResources() D3D12_MESSAGE_ID_RESOURCE_BARRIER_MISMATCHING_COMMAND_LIST_TYPE, }; D3D12_INFO_QUEUE_FILTER filter = {}; - filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.NumIDs = static_cast(std::size(hide)); filter.DenyList.pIDList = hide; d3dInfoQueue->AddStorageFilterEntries(&filter); } @@ -205,6 +215,9 @@ void DeviceResources::CreateDeviceResources() // Determine maximum supported feature level for this device static const D3D_FEATURE_LEVEL s_featureLevels[] = { +#if defined(NTDDI_WIN10_FE) && (NTDDI_VERSION >= NTDDI_WIN10_FE) + D3D_FEATURE_LEVEL_12_2, +#endif D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, D3D_FEATURE_LEVEL_11_1, @@ -213,7 +226,7 @@ void DeviceResources::CreateDeviceResources() D3D12_FEATURE_DATA_FEATURE_LEVELS featLevels = { - _countof(s_featureLevels), s_featureLevels, D3D_FEATURE_LEVEL_11_0 + static_cast(std::size(s_featureLevels)), s_featureLevels, D3D_FEATURE_LEVEL_11_0 }; hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &featLevels, sizeof(featLevels)); @@ -284,7 +297,7 @@ void DeviceResources::CreateDeviceResources() m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { - throw std::exception("CreateEvent"); + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } #ifdef _GAMING_XBOX @@ -297,7 +310,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { if (!m_window) { - throw std::exception("Call SetWindow with a valid window handle"); + throw std::logic_error("Call SetWindow with a valid Win32 window handle"); } // Wait until all previous GPU work is complete. @@ -323,7 +336,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -355,7 +368,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -366,7 +379,7 @@ void DeviceResources::CreateWindowSizeDependentResources() #else // _GAMING_DESKTOP - DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + const DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); // If the swap chain already exists, resize it, otherwise create one. if (m_swapChain) @@ -449,7 +462,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -464,7 +477,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -477,7 +490,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -588,12 +601,6 @@ void DeviceResources::HandleDeviceLost() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { -#ifdef _GAMING_XBOX - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); -#endif - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -601,7 +608,8 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState); m_commandList->ResourceBarrier(1, &barrier); } @@ -613,7 +621,9 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); m_commandList->ResourceBarrier(1, &barrier); } @@ -633,9 +643,12 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) m_commandQueue->PresentX(1, &planeParameters, nullptr) ); - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. -#else + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + +#else // _GAMING_DESKTOP // The first argument instructs DXGI to block until VSync, putting the application // to sleep until the next VSync. This ensures we don't waste any cycles rendering @@ -658,9 +671,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) ThrowIfFailed(hr); } -#endif - MoveToNextFrame(); +#endif } // Handle GPU suspend/resume @@ -686,13 +698,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -701,32 +713,20 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() -{ - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. #ifdef _GAMING_XBOX - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; -#else - m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); -#endif - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() +{ + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } -#ifdef _GAMING_XBOX // Set frame interval and register for frame events void DeviceResources::RegisterFrameEvents() { @@ -755,7 +755,30 @@ void DeviceResources::RegisterFrameEvents() nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE)); } -#else + +#else // _GAMING_DESKTOP + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + // This method acquires the first available hardware adapter that supports Direct3D 12. // If no such adapter can be found, try WARP. Otherwise throw an exception. void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) @@ -797,7 +820,7 @@ void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) // Try WARP12 instead if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) { - throw std::exception("WARP12 not available. Enable the 'Graphics Tools' optional feature"); + throw std::runtime_error("WARP12 not available. Enable the 'Graphics Tools' optional feature"); } OutputDebugStringA("Direct3D Adapter - WARP12\n"); @@ -806,7 +829,7 @@ void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) if (!adapter) { - throw std::exception("No Direct3D 12 device found"); + throw std::runtime_error("No Direct3D 12 device found"); } *ppAdapter = adapter.Detach(); diff --git a/Samples/Graphics/DynamicLOD/DeviceResources.h b/Samples/Graphics/DynamicLOD/DeviceResources.h index a920f13..0e0aeb0 100644 --- a/Samples/Graphics/DynamicLOD/DeviceResources.h +++ b/Samples/Graphics/DynamicLOD/DeviceResources.h @@ -22,9 +22,13 @@ namespace DX class DeviceResources { public: + static constexpr unsigned int c_ReverseDepth = 0x1; + static constexpr unsigned int c_AmplificationShaders = 0x2; + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, - UINT backBufferCount = 2) noexcept(false); + UINT backBufferCount = 2, + unsigned int flags = 0) noexcept(false); ~DeviceResources(); DeviceResources(DeviceResources&&) = default; @@ -45,6 +49,9 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; +#ifdef _GAMING_XBOX + void WaitForOrigin(); +#endif // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -68,6 +75,7 @@ namespace DX D3D12_RECT GetScissorRect() const noexcept { return m_scissorRect; } UINT GetCurrentFrameIndex() const noexcept { return m_backBufferIndex; } UINT GetBackBufferCount() const noexcept { return m_backBufferCount; } + unsigned int GetDeviceOptions() const noexcept { return m_options; } CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const noexcept { @@ -81,10 +89,10 @@ namespace DX } private: - void MoveToNextFrame(); #ifdef _GAMING_XBOX void RegisterFrameEvents(); #else + void MoveToNextFrame(); void GetAdapter(IDXGIAdapter1** ppAdapter); #endif @@ -131,6 +139,9 @@ namespace DX D3D_FEATURE_LEVEL m_d3dFeatureLevel; RECT m_outputSize; + // DeviceResources options (see flags above) + unsigned int m_options; + // The IDeviceNotify can be held directly as it owns the DeviceResources. IDeviceNotify* m_deviceNotify; }; diff --git a/Samples/Graphics/DynamicLOD/DynamicLOD.cpp b/Samples/Graphics/DynamicLOD/DynamicLOD.cpp index e42c2ba..279a971 100644 --- a/Samples/Graphics/DynamicLOD/DynamicLOD.cpp +++ b/Samples/Graphics/DynamicLOD/DynamicLOD.cpp @@ -14,7 +14,7 @@ #pragma warning( disable : 4324 4365 ) -extern void ExitSample(); +extern void ExitSample() noexcept; using namespace ATG; using namespace DirectX; @@ -27,15 +27,15 @@ namespace //-------------------------------------- // Definitions - static const wchar_t* s_sampleTitle = L"Dynamic LOD"; + const wchar_t* s_sampleTitle = L"Dynamic LOD"; - static const wchar_t* s_ampShaderFilename = L"DynamicLodAS.cso"; - static const wchar_t* s_meshShaderFilename = L"InstancedLodMS.cso"; - static const wchar_t* s_pixelShaderFilename = L"BasicMeshletPS.cso"; + const wchar_t* s_ampShaderFilename = L"DynamicLodAS.cso"; + const wchar_t* s_meshShaderFilename = L"InstancedLodMS.cso"; + const wchar_t* s_pixelShaderFilename = L"BasicMeshletPS.cso"; - static const wchar_t* s_lodFilenames[] = + const wchar_t* s_lodFilenames[] = { -#if _GAMING_DESKTOP +#ifdef _GAMING_DESKTOP L"ATGDragon\\Dragon_LOD0.sdkmesh", L"ATGDragon\\Dragon_LOD1.sdkmesh", L"ATGDragon\\Dragon_LOD2.sdkmesh", @@ -53,9 +53,9 @@ namespace }; #ifdef _GAMING_XBOX_SCARLETT - const uint32_t c_textureDataPitchAlign = D3D12XBOX_TEXTURE_DATA_PITCH_ALIGNMENT; + constexpr uint32_t c_textureDataPitchAlign = D3D12XBOX_TEXTURE_DATA_PITCH_ALIGNMENT; #else - const uint32_t c_textureDataPitchAlign = D3D12_TEXTURE_DATA_PITCH_ALIGNMENT; + constexpr uint32_t c_textureDataPitchAlign = D3D12_TEXTURE_DATA_PITCH_ALIGNMENT; #endif const HelpButtonAssignment c_buttonAssignment[] = @@ -72,9 +72,9 @@ namespace { HelpID::VIEW_BUTTON, L"Exit Sample" }, }; - constexpr float s_fovy = XM_PIDIV4; - constexpr uint32_t s_maxGroupsPerDispatch = 65536; - constexpr uint32_t s_maxInstances = AS_GROUP_SIZE * s_maxGroupsPerDispatch; + constexpr float c_fovy = XM_PIDIV4; + constexpr uint32_t c_maxGroupsPerDispatch = 65536; + constexpr uint32_t c_maxInstances = AS_GROUP_SIZE * c_maxGroupsPerDispatch; // Resource view offsets into the descriptor heap // The mesh & meshlet SRVs are laid out as they are referenced in shader code @@ -117,8 +117,7 @@ namespace } Sample::Sample() noexcept(false) - : m_deviceResources(std::make_unique()) - , m_displayWidth(0) + : m_displayWidth(0) , m_displayHeight(0) , m_frame(0) , m_uploadInstances(false) @@ -129,6 +128,9 @@ Sample::Sample() noexcept(false) , m_forceLod0(false) , m_renderHelp(false) { + m_deviceResources = std::make_unique( + DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_AmplificationShaders); m_deviceResources->RegisterDeviceNotify(this); } @@ -163,6 +165,10 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); +#ifdef _GAMING_XBOX + m_deviceResources->WaitForOrigin(); +#endif + m_timer.Tick([&]() { Update(m_timer); @@ -348,16 +354,16 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -378,7 +384,7 @@ void Sample::UpdateConstants(ID3D12GraphicsCommandList* commandList) XMStoreFloat4x4(&constants.View, XMMatrixTranspose(view)); XMStoreFloat4x4(&constants.ViewProj, XMMatrixTranspose(viewProj)); constants.RenderMode = m_renderMode; - constants.RecipTanHalfFovy = 1.0f / std::tanf(s_fovy * 0.5f); + constants.RecipTanHalfFovy = 1.0f / std::tanf(c_fovy * 0.5f); constants.LODCount = static_cast(m_lods.size()); constants.ForceLOD0 = m_forceLod0; constants.ForceVisible = m_forceVisible; @@ -568,7 +574,7 @@ void Sample::OnResuming() void Sample::OnWindowMoved() { - auto r = m_deviceResources->GetOutputSize(); + auto const r = m_deviceResources->GetOutputSize(); m_deviceResources->WindowSizeChanged(r.right, r.bottom); } @@ -581,7 +587,7 @@ void Sample::OnWindowSizeChanged(int width, int height) } // Properties -void Sample::GetDefaultSize(int& width, int& height) const +void Sample::GetDefaultSize(int& width, int& height) const noexcept { width = 1280; height = 720; @@ -592,7 +598,7 @@ void Sample::GetDefaultSize(int& width, int& height) const // These are the resources that depend on the device. void Sample::CreateDeviceDependentResources() { - auto device = static_cast(m_deviceResources->GetD3DDevice()); + auto device = m_deviceResources->GetD3DDevice(); // Check for Shader Model 6.5 and Mesh Shader feature support #ifdef _GAMING_DESKTOP @@ -722,7 +728,7 @@ void Sample::CreateDeviceDependentResources() } // Create our HUD objects - auto backBufferRts = RenderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState backBufferRts(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); m_controlHelp->RestoreDevice(device, resourceUpload, backBufferRts); auto spritePSD = SpriteBatchPipelineStateDescription(backBufferRts, &CommonStates::AlphaBlend); @@ -842,7 +848,7 @@ void Sample::CreateWindowSizeDependentResources() m_hudBatch->SetViewport(m_deviceResources->GetScreenViewport()); m_camera.SetWindow(m_displayWidth, m_displayHeight); - m_camera.SetProjectionParameters(s_fovy, 1.0f, 10000.0f, true); + m_camera.SetProjectionParameters(c_fovy, 1.0f, 10000.0f, true); m_camera.SetLookAt(Vector3(-200.0f, 200.0f, -200.0f), Vector3::Up * 40.0f); m_camera.SetSensitivity(500.0f, 100.0f, 1000.0f, 10.0f); @@ -964,9 +970,9 @@ void Sample::RegenerateInstances() } // Limit instance count to the number of instances - if (m_instances.size() > s_maxInstances) + if (m_instances.size() > c_maxInstances) { - m_instances.resize(s_maxInstances); + m_instances.resize(c_maxInstances); } // Only recreate instance-sized buffers if necessary. diff --git a/Samples/Graphics/DynamicLOD/DynamicLOD.h b/Samples/Graphics/DynamicLOD/DynamicLOD.h index 43c9472..9dae17f 100644 --- a/Samples/Graphics/DynamicLOD/DynamicLOD.h +++ b/Samples/Graphics/DynamicLOD/DynamicLOD.h @@ -38,7 +38,7 @@ public: void OnWindowSizeChanged(int width, int height); // Properties - void GetDefaultSize(int& width, int& height) const; + void GetDefaultSize(int& width, int& height) const noexcept; private: void Update(DX::StepTimer const& timer); diff --git a/Samples/Graphics/DynamicLOD/Main.cpp b/Samples/Graphics/DynamicLOD/Main.cpp index e22ea65..9eed737 100644 --- a/Samples/Graphics/DynamicLOD/Main.cpp +++ b/Samples/Graphics/DynamicLOD/Main.cpp @@ -20,6 +20,13 @@ using namespace DirectX; +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +#pragma warning(disable : 4061) + namespace { std::unique_ptr g_sample; @@ -27,11 +34,12 @@ namespace HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; #endif -}; +} LPCWSTR g_szAppName = L"Dynamic LOD"; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void ExitSample() noexcept; // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) @@ -55,7 +63,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp if (hr == E_GAMERUNTIME_DLL_NOT_FOUND || hr == E_GAMERUNTIME_VERSION_MISMATCH) { #ifdef _GAMING_DESKTOP - (void)MessageBoxW(nullptr, L"Game Runtime is not installed on this system or needs updating.", g_szAppName, MB_ICONERROR | MB_OK); + std::ignore = MessageBoxW(nullptr, L"Game Runtime is not installed on this system or needs updating.", g_szAppName, MB_ICONERROR | MB_OK); #endif } return 1; @@ -80,7 +88,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); wcex.lpszClassName = L"DynamicLODWindowClass"; if (!RegisterClassExW(&wcex)) return 1; @@ -134,7 +142,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -164,14 +172,14 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp #ifdef _GAMING_XBOX UnregisterAppStateChangeNotification(hPLM); - + CloseHandle(g_plmSuspendComplete); CloseHandle(g_plmSignalResume); #endif XGameRuntimeUninitialize(); - return (int) msg.wParam; + return static_cast(msg.wParam); } // Windows procedure @@ -232,7 +240,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); sample->OnResuming(); } @@ -246,7 +254,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) else { PAINTSTRUCT ps; - (void)BeginPaint(hWnd, &ps); + std::ignore = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); } break; @@ -298,12 +306,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_GETMINMAXINFO: - { - auto info = reinterpret_cast(lParam); - info->ptMinTrackSize.x = 320; - info->ptMinTrackSize.y = 200; - } - break; + if (lParam) + { + auto info = reinterpret_cast(lParam); + info->ptMinTrackSize.x = 320; + info->ptMinTrackSize.y = 200; + } + break; case WM_POWERBROADCAST: switch (wParam) @@ -360,7 +369,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); @@ -388,7 +397,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } // Exit helper -void ExitSample() +void ExitSample() noexcept { PostQuitMessage(0); } diff --git a/Samples/Graphics/DynamicLOD/StepTimer.h b/Samples/Graphics/DynamicLOD/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/DynamicLOD/StepTimer.h +++ b/Samples/Graphics/DynamicLOD/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/DynamicLOD/pch.h b/Samples/Graphics/DynamicLOD/pch.h index 6f655b9..9c637d7 100644 --- a/Samples/Graphics/DynamicLOD/pch.h +++ b/Samples/Graphics/DynamicLOD/pch.h @@ -41,14 +41,13 @@ #include -#if _GRDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GRDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT #include #include - #elif defined(_GAMING_XBOX) #error This sample does not support Xbox One #else @@ -69,17 +68,23 @@ #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include #include #include #include - -#include -#include +#include +#include +#include #ifdef _GAMING_XBOX #include @@ -122,9 +127,9 @@ namespace DX class com_exception : public std::exception { public: - com_exception(HRESULT hr) : result(hr) {} + com_exception(HRESULT hr) noexcept : result(hr) {} - virtual const char* what() const override + const char* what() const override { static char s_str[64] = {}; sprintf_s(s_str, "Failure with HRESULT of %08X", static_cast(result)); diff --git a/Samples/Graphics/ExecuteIndirect/DeviceResources.cpp b/Samples/Graphics/ExecuteIndirect/DeviceResources.cpp index d76fd63..fa67816 100644 --- a/Samples/Graphics/ExecuteIndirect/DeviceResources.cpp +++ b/Samples/Graphics/ExecuteIndirect/DeviceResources.cpp @@ -31,14 +31,13 @@ DeviceResources::DeviceResources( m_rtvDescriptorSize(0), m_screenViewport{}, m_scissorRect{}, - m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_backBufferFormat(backBufferFormat), m_depthBufferFormat(depthBufferFormat), m_backBufferCount(backBufferCount), m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), m_outputSize{0, 0, 1920, 1080}, - m_options(flags), - m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) + m_options(flags) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) { @@ -55,12 +54,16 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } } // Configures the Direct3D device, and stores handles to it and the device context. +#ifdef _GAMING_XBOX_SCARLETT +void DeviceResources::CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags) +#else void DeviceResources::CreateDeviceResources() +#endif { // Create the DX12 API device object. D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; @@ -77,6 +80,17 @@ void DeviceResources::CreateDeviceResources() params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#ifdef _GAMING_XBOX_SCARLETT + params.CreateDeviceFlags = createDeviceFlags; + +#if (_GXDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif +#endif HRESULT hr = D3D12XboxCreateDevice( nullptr, @@ -107,7 +121,7 @@ void DeviceResources::CreateDeviceResources() // Create descriptor heaps for render target views and depth stencil views. D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; - rtvDescriptorHeapDesc.NumDescriptors = (m_options & c_EnableHDR) ? (m_backBufferCount * 2) : m_backBufferCount; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); @@ -152,31 +166,46 @@ void DeviceResources::CreateDeviceResources() m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { - throw std::exception("CreateEvent"); + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } - if (m_options & c_Enable4K_UHD) + if (m_options & (c_Enable4K_UHD | c_EnableQHD)) { switch (XSystemGetDeviceType()) { case XSystemDeviceType::XboxOne: case XSystemDeviceType::XboxOneS: - case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: - m_options &= ~c_Enable4K_UHD; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080)\n"); -#endif + m_options &= ~(c_Enable4K_UHD | c_EnableQHD); break; + case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: + m_options &= ~c_Enable4K_UHD; + if (m_options & c_EnableQHD) + { + m_outputSize = { 0, 0, 2560, 1440 }; + } + break; + + case XSystemDeviceType::XboxScarlettAnaconda /* Xbox Series X */: + case XSystemDeviceType::XboxOneXDevkit: + case XSystemDeviceType::XboxScarlettDevkit: default: - m_outputSize = { 0, 0, 3840, 2160 }; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160)\n"); -#endif + m_outputSize = (m_options & c_Enable4K_UHD) ? RECT{ 0, 0, 3840, 2160 } : RECT{ 0, 0, 2560, 1440 }; break; } } +#ifdef _DEBUG + const char* info = nullptr; + switch (m_outputSize.bottom) + { + case 2160: info = "INFO: Swapchain using 4k (3840 x 2160)\n"; break; + case 1440: info = "INFO: Swapchain using 1440p (2560 x 1440)\n"; break; + default: info = "INFO: Swapchain using 1080p (1920 x 1080)\n"; break; + } + OutputDebugStringA(info); +#endif + RegisterFrameEvents(); } @@ -185,7 +214,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { if (!m_window) { - throw std::exception("Call SetWindow with a valid window handle"); + throw std::logic_error("Call SetWindow with a valid Win32 window handle"); } // Wait until all previous GPU work is complete. @@ -198,7 +227,6 @@ void DeviceResources::CreateWindowSizeDependentResources() for (UINT n = 0; n < m_backBufferCount; n++) { m_renderTargets[n].Reset(); - m_renderTargetsGameDVR[n].Reset(); m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; } @@ -208,7 +236,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -219,6 +247,13 @@ void DeviceResources::CreateWindowSizeDependentResources() ); swapChainBufferDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; +#ifdef _GAMING_XBOX_XBOXONE + if (m_options & c_EnableHDR) + { + swapChainBufferDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_AUTOMATIC_GAMEDVR_TONE_MAP; + } +#endif + D3D12_CLEAR_VALUE swapChainOptimizedClearValue = {}; swapChainOptimizedClearValue.Format = m_backBufferFormat; @@ -240,41 +275,12 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); } - if (m_options & c_EnableHDR) - { - swapChainBufferDesc.Format = swapChainOptimizedClearValue.Format = m_gameDVRFormat; - - for (UINT n = 0; n < m_backBufferCount; n++) - { - ThrowIfFailed(m_d3dDevice->CreateCommittedResource( - &swapChainHeapProperties, - D3D12_HEAP_FLAG_ALLOW_DISPLAY, - &swapChainBufferDesc, - D3D12_RESOURCE_STATE_PRESENT, - &swapChainOptimizedClearValue, - IID_GRAPHICS_PPV_ARGS(m_renderTargetsGameDVR[n].GetAddressOf()))); - - wchar_t name[25] = {}; - swprintf_s(name, L"GameDVR Render target %u", n); - m_renderTargetsGameDVR[n]->SetName(name); - - D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; - rtvDesc.Format = m_gameDVRFormat; - rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + n), m_rtvDescriptorSize); - m_d3dDevice->CreateRenderTargetView(m_renderTargetsGameDVR[n].Get(), &rtvDesc, rtvDescriptorGameDVR); - } - } - // Reset the index to the current back buffer. m_backBufferIndex = 0; @@ -282,7 +288,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -295,7 +301,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -331,10 +337,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -342,23 +344,10 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), - beforeState, afterState), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, afterState); + m_commandList->ResourceBarrier(1, &barrier); } } @@ -368,20 +357,10 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); } // Send the command list off to the GPU for processing. @@ -389,32 +368,24 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); // Present the backbuffer using the PresentX API. - D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters[2] = {}; - planeParameters[0].Token = planeParameters[1].Token = m_framePipelineToken; - planeParameters[0].ResourceCount = planeParameters[1].ResourceCount = 1; - planeParameters[0].ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); + D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters = {}; + planeParameters.Token = m_framePipelineToken; + planeParameters.ResourceCount = 1; + planeParameters.ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); if (m_options & c_EnableHDR) { - planeParameters[0].pSrcViewRects = planeParameters[1].pSrcViewRects = &m_outputSize; - planeParameters[0].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; - planeParameters[1].ppResources = m_renderTargetsGameDVR[m_backBufferIndex].GetAddressOf(); - planeParameters[1].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; - - ThrowIfFailed( - m_commandQueue->PresentX(2, planeParameters, params) - ); - } - else - { - ThrowIfFailed( - m_commandQueue->PresentX(1, planeParameters, params) - ); + planeParameters.ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; } - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + ThrowIfFailed( + m_commandQueue->PresentX(1, &planeParameters, params) + ); - MoveToNextFrame(); + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -436,13 +407,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -451,25 +422,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/Graphics/ExecuteIndirect/DeviceResources.h b/Samples/Graphics/ExecuteIndirect/DeviceResources.h index 1d26b17..4924894 100644 --- a/Samples/Graphics/ExecuteIndirect/DeviceResources.h +++ b/Samples/Graphics/ExecuteIndirect/DeviceResources.h @@ -10,8 +10,11 @@ namespace DX class DeviceResources { public: - static constexpr unsigned int c_Enable4K_UHD = 0x1; - static constexpr unsigned int c_EnableHDR = 0x2; + static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_ReverseDepth = 0x8; + static constexpr unsigned int c_AmplificationShaders = 0x10; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -25,7 +28,11 @@ namespace DX DeviceResources(DeviceResources const&) = delete; DeviceResources& operator= (DeviceResources const&) = delete; +#ifdef _GAMING_XBOX_SCARLETT + void CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags = D3D12XBOX_CREATE_DEVICE_FLAG_NONE); +#else void CreateDeviceResources(); +#endif void CreateWindowSizeDependentResources(); void SetWindow(HWND window) noexcept { m_window = window; } void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT, @@ -35,6 +42,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -67,19 +75,7 @@ namespace DX return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); } - // Direct3D HDR Game DVR support for Xbox One. - ID3D12Resource* GetGameDVRRenderTarget() const noexcept { return m_renderTargetsGameDVR[m_backBufferIndex].Get(); } - DXGI_FORMAT GetGameDVRFormat() const noexcept { return m_gameDVRFormat; } - - CD3DX12_CPU_DESCRIPTOR_HANDLE GetGameDVRRenderTargetView() const noexcept - { - return CD3DX12_CPU_DESCRIPTOR_HANDLE( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + m_backBufferIndex), m_rtvDescriptorSize); - } - private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; @@ -126,9 +122,5 @@ namespace DX // DeviceResources options (see flags above) unsigned int m_options; - - // Direct3D HDR Game DVR support for Xbox One. - Microsoft::WRL::ComPtr m_renderTargetsGameDVR[MAX_BACK_BUFFER_COUNT]; - DXGI_FORMAT m_gameDVRFormat; }; } diff --git a/Samples/Graphics/ExecuteIndirect/ExecuteIndirect.cpp b/Samples/Graphics/ExecuteIndirect/ExecuteIndirect.cpp index 6fdbbc3..24dcfbf 100644 --- a/Samples/Graphics/ExecuteIndirect/ExecuteIndirect.cpp +++ b/Samples/Graphics/ExecuteIndirect/ExecuteIndirect.cpp @@ -10,7 +10,7 @@ #include "ATGColors.h" -extern void ExitSample(); +extern void ExitSample() noexcept; using namespace DirectX; @@ -68,7 +68,7 @@ void Sample::Initialize(HWND window) m_deviceResources->SetWindow(window); - m_deviceResources->CreateDeviceResources(); + m_deviceResources->CreateDeviceResources(); CreateDeviceDependentResources(); m_deviceResources->CreateWindowSizeDependentResources(); @@ -81,6 +81,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); @@ -267,16 +269,16 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -499,7 +501,7 @@ void Sample::ComputeCulling() m_constantBufferFrustum->Unmap(0, &constantBufferFrustumRange); // Initialize Count to 0 - UINT clearValues[4] = {}; + const UINT clearValues[4] = {}; commandList->ClearUnorderedAccessViewUint( m_countDescriptorGPU, m_countDescriptorCPU, @@ -628,7 +630,7 @@ void Sample::CreateDeviceDependentResources() m_resourceDescriptorHeap->GetCpuHandle(ResourceDescriptors::FontController), m_resourceDescriptorHeap->GetGpuHandle(ResourceDescriptors::FontController)); - RenderTargetState renderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState renderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); SpriteBatchPipelineStateDescription pipelineDescription(renderTargetState); m_spriteBatch = std::make_unique(device, resourceUpload, pipelineDescription); @@ -638,7 +640,7 @@ void Sample::CreateDeviceDependentResources() // Allocate all memory resources that change on a window SizeChanged event. void Sample::CreateWindowSizeDependentResources() { - auto outputSize = m_deviceResources->GetOutputSize(); + auto const outputSize = m_deviceResources->GetOutputSize(); // Initial camera values m_cameraPosition = XMVectorSet(0.0f, 0.0f, -10.0f, 1.0f); @@ -732,9 +734,9 @@ void Sample::InitializeMeshes() Index faceIndices[faces][indicesPerFace] = { { 0, 1, 2, }, - { 0, 2, 3, }, - { 0, 3, 1, }, - { 3, 2, 1, }, + { 0, 2, 3, }, + { 0, 3, 1, }, + { 3, 2, 1, }, }; for (uint32_t iFace = 0; iFace < faces; ++iFace) { @@ -767,11 +769,11 @@ void Sample::InitializeMeshes() Index faceIndices[faces][indicesPerFace] = { { 0, 1, 3, 2, }, - { 0, 4, 5, 1, }, - { 0, 2, 6, 4, }, - { 4, 6, 7, 5, }, - { 2, 3, 7, 6, }, - { 1, 5, 7, 3, }, + { 0, 4, 5, 1, }, + { 0, 2, 6, 4, }, + { 4, 6, 7, 5, }, + { 2, 3, 7, 6, }, + { 1, 5, 7, 3, }, }; for (uint32_t iFace = 0; iFace < faces; ++iFace) { @@ -806,13 +808,13 @@ void Sample::InitializeMeshes() Index faceIndices[faces][indicesPerFace] = { { 0, 3, 4 }, - { 3, 1, 4 }, - { 1, 2, 4 }, - { 2, 0, 4 }, - { 3, 0, 5 }, - { 1, 3, 5 }, - { 2, 1, 5 }, - { 0, 2, 5 }, + { 3, 1, 4 }, + { 1, 2, 4 }, + { 2, 0, 4 }, + { 3, 0, 5 }, + { 1, 3, 5 }, + { 2, 1, 5 }, + { 0, 2, 5 }, }; for (uint32_t iFace = 0; iFace < faces; ++iFace) { @@ -860,17 +862,17 @@ void Sample::InitializeMeshes() Index faceIndices[faces][indicesPerFace] = { { 0, 12, 13, 1, 8, }, - { 0, 8, 9, 2, 16, }, - { 0, 16, 17, 4, 12, }, - { 1, 18, 3, 9, 8, }, - { 1, 13, 5, 19, 18, }, - { 2, 9, 3, 15, 14, }, - { 2, 14, 6, 17, 16, }, - { 3, 18, 19, 7, 15, }, - { 4, 10, 5, 13, 12, }, - { 4, 17, 6, 11, 10, }, - { 5, 10, 11, 7, 19, }, - { 6, 14, 15, 7, 11, }, + { 0, 8, 9, 2, 16, }, + { 0, 16, 17, 4, 12, }, + { 1, 18, 3, 9, 8, }, + { 1, 13, 5, 19, 18, }, + { 2, 9, 3, 15, 14, }, + { 2, 14, 6, 17, 16, }, + { 3, 18, 19, 7, 15, }, + { 4, 10, 5, 13, 12, }, + { 4, 17, 6, 11, 10, }, + { 5, 10, 11, 7, 19, }, + { 6, 14, 15, 7, 11, }, }; for (uint32_t iFace = 0; iFace < faces; ++iFace) { @@ -917,25 +919,25 @@ void Sample::InitializeMeshes() Index faceIndices[faces][indicesPerFace] = { { 0, 4, 2, }, - { 0, 2, 5, }, - { 0, 5, 10, }, - { 0, 10, 8, }, - { 0, 8, 4, }, - { 3, 1, 7, }, - { 3, 7, 11, }, - { 3, 11, 9, }, - { 3, 9, 6, }, - { 3, 6, 1, }, - { 4, 9, 2, }, - { 2, 9, 11, }, - { 5, 2, 11, }, - { 5, 11, 7, }, - { 5, 7, 10, }, - { 10, 7, 1, }, - { 10, 1, 8, }, - { 8, 1, 6, }, - { 8, 6, 4, }, - { 4, 6, 9, }, + { 0, 2, 5, }, + { 0, 5, 10, }, + { 0, 10, 8, }, + { 0, 8, 4, }, + { 3, 1, 7, }, + { 3, 7, 11, }, + { 3, 11, 9, }, + { 3, 9, 6, }, + { 3, 6, 1, }, + { 4, 9, 2, }, + { 2, 9, 11, }, + { 5, 2, 11, }, + { 5, 11, 7, }, + { 5, 7, 10, }, + { 10, 7, 1, }, + { 10, 1, 8, }, + { 8, 1, 6, }, + { 8, 6, 4, }, + { 4, 6, 9, }, }; for (uint32_t iFace = 0; iFace < faces; ++iFace) { diff --git a/Samples/Graphics/ExecuteIndirect/ExecuteIndirect.h b/Samples/Graphics/ExecuteIndirect/ExecuteIndirect.h index 27953d4..695608d 100644 --- a/Samples/Graphics/ExecuteIndirect/ExecuteIndirect.h +++ b/Samples/Graphics/ExecuteIndirect/ExecuteIndirect.h @@ -25,6 +25,13 @@ class Sample public: Sample() noexcept(false); + ~Sample() = default; + + Sample(Sample&&) = default; + Sample& operator= (Sample&&) = default; + + Sample(Sample const&) = delete; + Sample& operator= (Sample const&) = delete; // Initialization and management void Initialize(HWND window); @@ -35,9 +42,11 @@ public: // Messages void OnSuspending(); void OnResuming(); + void OnConstrained() {} + void OnUnConstrained() {} // Properties - bool RequestHDRMode() const { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } + bool RequestHDRMode() const noexcept { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } private: diff --git a/Samples/Graphics/ExecuteIndirect/Main.cpp b/Samples/Graphics/ExecuteIndirect/Main.cpp index a60b9d8..3b87bcf 100644 --- a/Samples/Graphics/ExecuteIndirect/Main.cpp +++ b/Samples/Graphics/ExecuteIndirect/Main.cpp @@ -18,16 +18,25 @@ using namespace DirectX; +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +#pragma warning(disable : 4061) + namespace { std::unique_ptr g_sample; HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; -}; +} bool g_HDRMode = false; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void SetDisplayMode() noexcept; +void ExitSample() noexcept; // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) @@ -58,6 +67,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp // Register class and create window PAPPSTATE_REGISTRATION hPLM = {}; + PAPPCONSTRAIN_REGISTRATION hPLM2 = {}; + { // Register class WNDCLASSEXA wcex = {}; @@ -66,7 +77,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.lpszClassName = u8"ExecuteIndirectWindowClass"; - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); if (!RegisterClassExA(&wcex)) return 1; @@ -79,17 +90,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp ShowWindow(hwnd, nCmdShow); - if (g_sample->RequestHDRMode()) - { - // Request HDR mode. - auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); - - g_HDRMode = (result == XDisplayHdrModeResult::Enabled); - - #ifdef _DEBUG - OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); - #endif - } + SetDisplayMode(); SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(g_sample.get())); @@ -116,7 +117,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -124,6 +125,13 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp } }, hwnd, &hPLM)) return 1; + + if (RegisterAppConstrainedChangeNotification([](BOOLEAN constrained, PVOID context) + { + // To ensure we use the main UI thread to process the notification, we self-post a message + SendMessage(reinterpret_cast(context), WM_USER + 1, (constrained) ? 1u : 0u, 0); + }, hwnd, &hPLM2)) + return 1; } // Main message loop @@ -144,13 +152,14 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp g_sample.reset(); UnregisterAppStateChangeNotification(hPLM); - + UnregisterAppConstrainedChangeNotification(hPLM2); + CloseHandle(g_plmSuspendComplete); CloseHandle(g_plmSignalResume); XGameRuntimeUninitialize(); - return (int) msg.wParam; + return static_cast(msg.wParam); } // Windows procedure @@ -168,18 +177,52 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); + + SetDisplayMode(); sample->OnResuming(); } break; + + case WM_USER + 1: + if (sample) + { + if (wParam) + { + sample->OnConstrained(); + } + else + { + SetDisplayMode(); + + sample->OnUnConstrained(); + } + } + break; } return DefWindowProc(hWnd, message, wParam, lParam); } +// HDR helper +void SetDisplayMode() noexcept +{ + if (g_sample && g_sample->RequestHDRMode()) + { + // Request HDR mode. + auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); + + g_HDRMode = (result == XDisplayHdrModeResult::Enabled); + +#ifdef _DEBUG + OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); +#endif + } +} + // Exit helper -void ExitSample() +void ExitSample() noexcept { PostQuitMessage(0); } diff --git a/Samples/Graphics/ExecuteIndirect/Readme.docx b/Samples/Graphics/ExecuteIndirect/Readme.docx index 241e8f8..38e99cc 100644 Binary files a/Samples/Graphics/ExecuteIndirect/Readme.docx and b/Samples/Graphics/ExecuteIndirect/Readme.docx differ diff --git a/Samples/Graphics/ExecuteIndirect/StepTimer.h b/Samples/Graphics/ExecuteIndirect/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/ExecuteIndirect/StepTimer.h +++ b/Samples/Graphics/ExecuteIndirect/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/ExecuteIndirect/pch.h b/Samples/Graphics/ExecuteIndirect/pch.h index 5810e25..478f4e1 100644 --- a/Samples/Graphics/ExecuteIndirect/pch.h +++ b/Samples/Graphics/ExecuteIndirect/pch.h @@ -37,8 +37,8 @@ #include -#if _GXDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GXDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -56,40 +56,48 @@ #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include #include +#include +#include +#include -#include -#include #include + #include #include +#include "DescriptorHeap.h" #include "GamePad.h" #include "GraphicsMemory.h" #include "RenderTargetState.h" - -#include "ControllerFont.h" -#include "DescriptorHeap.h" -#include "PerformanceTimersXbox.h" -#include "ReadData.h" #include "ResourceUploadBatch.h" #include "SpriteBatch.h" #include "SpriteFont.h" +#include "ControllerFont.h" +#include "PerformanceTimersXbox.h" +#include "ReadData.h" + namespace DX { // Helper class for COM exceptions class com_exception : public std::exception { public: - com_exception(HRESULT hr) : result(hr) {} + com_exception(HRESULT hr) noexcept : result(hr) {} - virtual const char* what() const override + const char* what() const override { static char s_str[64] = {}; sprintf_s(s_str, "Failure with HRESULT of %08X", static_cast(result)); diff --git a/Samples/Graphics/FastBlockCompress/DeviceResources.cpp b/Samples/Graphics/FastBlockCompress/DeviceResources.cpp index d76fd63..fa67816 100644 --- a/Samples/Graphics/FastBlockCompress/DeviceResources.cpp +++ b/Samples/Graphics/FastBlockCompress/DeviceResources.cpp @@ -31,14 +31,13 @@ DeviceResources::DeviceResources( m_rtvDescriptorSize(0), m_screenViewport{}, m_scissorRect{}, - m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_backBufferFormat(backBufferFormat), m_depthBufferFormat(depthBufferFormat), m_backBufferCount(backBufferCount), m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), m_outputSize{0, 0, 1920, 1080}, - m_options(flags), - m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) + m_options(flags) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) { @@ -55,12 +54,16 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } } // Configures the Direct3D device, and stores handles to it and the device context. +#ifdef _GAMING_XBOX_SCARLETT +void DeviceResources::CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags) +#else void DeviceResources::CreateDeviceResources() +#endif { // Create the DX12 API device object. D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; @@ -77,6 +80,17 @@ void DeviceResources::CreateDeviceResources() params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#ifdef _GAMING_XBOX_SCARLETT + params.CreateDeviceFlags = createDeviceFlags; + +#if (_GXDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif +#endif HRESULT hr = D3D12XboxCreateDevice( nullptr, @@ -107,7 +121,7 @@ void DeviceResources::CreateDeviceResources() // Create descriptor heaps for render target views and depth stencil views. D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; - rtvDescriptorHeapDesc.NumDescriptors = (m_options & c_EnableHDR) ? (m_backBufferCount * 2) : m_backBufferCount; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); @@ -152,31 +166,46 @@ void DeviceResources::CreateDeviceResources() m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { - throw std::exception("CreateEvent"); + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } - if (m_options & c_Enable4K_UHD) + if (m_options & (c_Enable4K_UHD | c_EnableQHD)) { switch (XSystemGetDeviceType()) { case XSystemDeviceType::XboxOne: case XSystemDeviceType::XboxOneS: - case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: - m_options &= ~c_Enable4K_UHD; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080)\n"); -#endif + m_options &= ~(c_Enable4K_UHD | c_EnableQHD); break; + case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: + m_options &= ~c_Enable4K_UHD; + if (m_options & c_EnableQHD) + { + m_outputSize = { 0, 0, 2560, 1440 }; + } + break; + + case XSystemDeviceType::XboxScarlettAnaconda /* Xbox Series X */: + case XSystemDeviceType::XboxOneXDevkit: + case XSystemDeviceType::XboxScarlettDevkit: default: - m_outputSize = { 0, 0, 3840, 2160 }; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160)\n"); -#endif + m_outputSize = (m_options & c_Enable4K_UHD) ? RECT{ 0, 0, 3840, 2160 } : RECT{ 0, 0, 2560, 1440 }; break; } } +#ifdef _DEBUG + const char* info = nullptr; + switch (m_outputSize.bottom) + { + case 2160: info = "INFO: Swapchain using 4k (3840 x 2160)\n"; break; + case 1440: info = "INFO: Swapchain using 1440p (2560 x 1440)\n"; break; + default: info = "INFO: Swapchain using 1080p (1920 x 1080)\n"; break; + } + OutputDebugStringA(info); +#endif + RegisterFrameEvents(); } @@ -185,7 +214,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { if (!m_window) { - throw std::exception("Call SetWindow with a valid window handle"); + throw std::logic_error("Call SetWindow with a valid Win32 window handle"); } // Wait until all previous GPU work is complete. @@ -198,7 +227,6 @@ void DeviceResources::CreateWindowSizeDependentResources() for (UINT n = 0; n < m_backBufferCount; n++) { m_renderTargets[n].Reset(); - m_renderTargetsGameDVR[n].Reset(); m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; } @@ -208,7 +236,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -219,6 +247,13 @@ void DeviceResources::CreateWindowSizeDependentResources() ); swapChainBufferDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; +#ifdef _GAMING_XBOX_XBOXONE + if (m_options & c_EnableHDR) + { + swapChainBufferDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_AUTOMATIC_GAMEDVR_TONE_MAP; + } +#endif + D3D12_CLEAR_VALUE swapChainOptimizedClearValue = {}; swapChainOptimizedClearValue.Format = m_backBufferFormat; @@ -240,41 +275,12 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); } - if (m_options & c_EnableHDR) - { - swapChainBufferDesc.Format = swapChainOptimizedClearValue.Format = m_gameDVRFormat; - - for (UINT n = 0; n < m_backBufferCount; n++) - { - ThrowIfFailed(m_d3dDevice->CreateCommittedResource( - &swapChainHeapProperties, - D3D12_HEAP_FLAG_ALLOW_DISPLAY, - &swapChainBufferDesc, - D3D12_RESOURCE_STATE_PRESENT, - &swapChainOptimizedClearValue, - IID_GRAPHICS_PPV_ARGS(m_renderTargetsGameDVR[n].GetAddressOf()))); - - wchar_t name[25] = {}; - swprintf_s(name, L"GameDVR Render target %u", n); - m_renderTargetsGameDVR[n]->SetName(name); - - D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; - rtvDesc.Format = m_gameDVRFormat; - rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + n), m_rtvDescriptorSize); - m_d3dDevice->CreateRenderTargetView(m_renderTargetsGameDVR[n].Get(), &rtvDesc, rtvDescriptorGameDVR); - } - } - // Reset the index to the current back buffer. m_backBufferIndex = 0; @@ -282,7 +288,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -295,7 +301,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -331,10 +337,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -342,23 +344,10 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), - beforeState, afterState), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, afterState); + m_commandList->ResourceBarrier(1, &barrier); } } @@ -368,20 +357,10 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); } // Send the command list off to the GPU for processing. @@ -389,32 +368,24 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); // Present the backbuffer using the PresentX API. - D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters[2] = {}; - planeParameters[0].Token = planeParameters[1].Token = m_framePipelineToken; - planeParameters[0].ResourceCount = planeParameters[1].ResourceCount = 1; - planeParameters[0].ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); + D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters = {}; + planeParameters.Token = m_framePipelineToken; + planeParameters.ResourceCount = 1; + planeParameters.ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); if (m_options & c_EnableHDR) { - planeParameters[0].pSrcViewRects = planeParameters[1].pSrcViewRects = &m_outputSize; - planeParameters[0].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; - planeParameters[1].ppResources = m_renderTargetsGameDVR[m_backBufferIndex].GetAddressOf(); - planeParameters[1].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; - - ThrowIfFailed( - m_commandQueue->PresentX(2, planeParameters, params) - ); - } - else - { - ThrowIfFailed( - m_commandQueue->PresentX(1, planeParameters, params) - ); + planeParameters.ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; } - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + ThrowIfFailed( + m_commandQueue->PresentX(1, &planeParameters, params) + ); - MoveToNextFrame(); + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -436,13 +407,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -451,25 +422,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/Graphics/FastBlockCompress/DeviceResources.h b/Samples/Graphics/FastBlockCompress/DeviceResources.h index 1d26b17..4924894 100644 --- a/Samples/Graphics/FastBlockCompress/DeviceResources.h +++ b/Samples/Graphics/FastBlockCompress/DeviceResources.h @@ -10,8 +10,11 @@ namespace DX class DeviceResources { public: - static constexpr unsigned int c_Enable4K_UHD = 0x1; - static constexpr unsigned int c_EnableHDR = 0x2; + static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_ReverseDepth = 0x8; + static constexpr unsigned int c_AmplificationShaders = 0x10; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -25,7 +28,11 @@ namespace DX DeviceResources(DeviceResources const&) = delete; DeviceResources& operator= (DeviceResources const&) = delete; +#ifdef _GAMING_XBOX_SCARLETT + void CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags = D3D12XBOX_CREATE_DEVICE_FLAG_NONE); +#else void CreateDeviceResources(); +#endif void CreateWindowSizeDependentResources(); void SetWindow(HWND window) noexcept { m_window = window; } void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT, @@ -35,6 +42,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -67,19 +75,7 @@ namespace DX return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); } - // Direct3D HDR Game DVR support for Xbox One. - ID3D12Resource* GetGameDVRRenderTarget() const noexcept { return m_renderTargetsGameDVR[m_backBufferIndex].Get(); } - DXGI_FORMAT GetGameDVRFormat() const noexcept { return m_gameDVRFormat; } - - CD3DX12_CPU_DESCRIPTOR_HANDLE GetGameDVRRenderTargetView() const noexcept - { - return CD3DX12_CPU_DESCRIPTOR_HANDLE( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + m_backBufferIndex), m_rtvDescriptorSize); - } - private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; @@ -126,9 +122,5 @@ namespace DX // DeviceResources options (see flags above) unsigned int m_options; - - // Direct3D HDR Game DVR support for Xbox One. - Microsoft::WRL::ComPtr m_renderTargetsGameDVR[MAX_BACK_BUFFER_COUNT]; - DXGI_FORMAT m_gameDVRFormat; }; } diff --git a/Samples/Graphics/FastBlockCompress/FastBlockCompress.cpp b/Samples/Graphics/FastBlockCompress/FastBlockCompress.cpp index 0544a48..ddea082 100644 --- a/Samples/Graphics/FastBlockCompress/FastBlockCompress.cpp +++ b/Samples/Graphics/FastBlockCompress/FastBlockCompress.cpp @@ -12,7 +12,7 @@ #include "ControllerFont.h" #include "ReadData.h" -extern void ExitSample(); +extern void ExitSample() noexcept; using namespace DirectX; @@ -20,9 +20,9 @@ using Microsoft::WRL::ComPtr; namespace { - const uint32_t MAX_TEXTURE_WIDTH = 2048; // 2048x2048 + constexpr uint32_t MAX_TEXTURE_WIDTH = 2048; // 2048x2048 - const uint32_t RMS_THREADGROUP_WIDTH = 64; + constexpr uint32_t RMS_THREADGROUP_WIDTH = 64; enum RMSRootParameterIndex { @@ -61,8 +61,8 @@ namespace static_assert((sizeof(ConstantBufferQuad) % 16) == 0, "CB size not padded correctly"); - const float c_zoomSpeed = 0.5f; - const float c_panSpeed = 0.5f; + constexpr float c_zoomSpeed = 0.5f; + constexpr float c_panSpeed = 0.5f; inline XMFLOAT2 RMSComputeResult(ID3D12Resource* buffer, float width) { @@ -114,7 +114,7 @@ void Sample::Initialize(HWND window) m_deviceResources->SetWindow(window); - m_deviceResources->CreateDeviceResources(); + m_deviceResources->CreateDeviceResources(); CreateDeviceDependentResources(); m_deviceResources->CreateWindowSizeDependentResources(); @@ -127,6 +127,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); @@ -310,7 +312,7 @@ void Sample::Update(DX::StepTimer const& timer) m_gpuTimer.BeginFrame(m_computeCommandList.Get()); ID3D12DescriptorHeap* pHeaps[] = { m_resourceDescriptors->Heap() }; - m_computeCommandList->SetDescriptorHeaps(_countof(pHeaps), pHeaps); + m_computeCommandList->SetDescriptorHeaps(static_cast(std::size(pHeaps)), pHeaps); auto img = m_images[m_currentImage].get(); @@ -506,9 +508,9 @@ void Sample::Render() m_deviceResources->Prepare(); Clear(); - auto size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); - auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(UINT(size.right), UINT(size.bottom)); + auto const safe = SimpleMath::Viewport::ComputeTitleSafeArea(UINT(size.right), UINT(size.bottom)); auto commandList = m_deviceResources->GetCommandList(); PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); @@ -518,7 +520,7 @@ void Sample::Render() { m_resourceDescriptors->Heap() }; - commandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps); + commandList->SetDescriptorHeaps(static_cast(std::size(descriptorHeaps)), descriptorHeaps); // Draw images auto img = m_images[m_currentImage].get(); @@ -599,7 +601,7 @@ void Sample::Render() viewPort.MaxDepth = 1; commandList->RSSetViewports(1, &viewPort); - RECT rct = { long(viewPort.TopLeftX), long(viewPort.TopLeftY), long(viewPort.TopLeftX + viewPort.Width), long(viewPort.TopLeftY + viewPort.Height) }; + const RECT rct = { long(viewPort.TopLeftX), long(viewPort.TopLeftY), long(viewPort.TopLeftX + viewPort.Width), long(viewPort.TopLeftY + viewPort.Height) }; commandList->RSSetScissorRects(1, &rct); if (m_toggleOriginal) @@ -770,14 +772,14 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, nullptr); commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -809,11 +811,9 @@ void Sample::CreateDeviceDependentResources() m_graphicsMemory = std::make_unique(device); - RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); m_resourceDescriptors = std::make_unique(device, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 256, Descriptors::Count); diff --git a/Samples/Graphics/FastBlockCompress/FastBlockCompress.h b/Samples/Graphics/FastBlockCompress/FastBlockCompress.h index 30ba68e..a446e81 100644 --- a/Samples/Graphics/FastBlockCompress/FastBlockCompress.h +++ b/Samples/Graphics/FastBlockCompress/FastBlockCompress.h @@ -51,6 +51,13 @@ class Sample public: Sample() noexcept(false); + ~Sample() = default; + + Sample(Sample&&) = default; + Sample& operator= (Sample&&) = default; + + Sample(Sample const&) = delete; + Sample& operator= (Sample const&) = delete; // Initialization and management void Initialize(HWND window); @@ -61,9 +68,11 @@ public: // Messages void OnSuspending(); void OnResuming(); + void OnConstrained() {} + void OnUnConstrained() {} // Properties - bool RequestHDRMode() const { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } + bool RequestHDRMode() const noexcept { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } private: @@ -140,10 +149,10 @@ private: Microsoft::WRL::ComPtr m_fbcTexture; void* m_fbcTextureMem; - std::vector m_srvFBC; + std::vector m_srvFBC; - DX::GPUComputeTimer m_gpuTimer; - DX::CPUTimer m_cpuTimer; + DX::GPUComputeTimer m_gpuTimer; + DX::CPUTimer m_cpuTimer; Microsoft::WRL::ComPtr m_computeAllocator; Microsoft::WRL::ComPtr m_computeCommandQueue; diff --git a/Samples/Graphics/FastBlockCompress/Main.cpp b/Samples/Graphics/FastBlockCompress/Main.cpp index ff1207e..ccec991 100644 --- a/Samples/Graphics/FastBlockCompress/Main.cpp +++ b/Samples/Graphics/FastBlockCompress/Main.cpp @@ -18,16 +18,25 @@ using namespace DirectX; +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +#pragma warning(disable : 4061) + namespace { std::unique_ptr g_sample; HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; -}; +} bool g_HDRMode = false; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void SetDisplayMode() noexcept; +void ExitSample() noexcept; // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) @@ -58,6 +67,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp // Register class and create window PAPPSTATE_REGISTRATION hPLM = {}; + PAPPCONSTRAIN_REGISTRATION hPLM2 = {}; + { // Register class WNDCLASSEXA wcex = {}; @@ -66,7 +77,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.lpszClassName = u8"FastBlockCompressWindowClass"; - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); if (!RegisterClassExA(&wcex)) return 1; @@ -79,17 +90,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp ShowWindow(hwnd, nCmdShow); - if (g_sample->RequestHDRMode()) - { - // Request HDR mode. - auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); - - g_HDRMode = (result == XDisplayHdrModeResult::Enabled); - - #ifdef _DEBUG - OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); - #endif - } + SetDisplayMode(); SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(g_sample.get())); @@ -116,7 +117,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -124,6 +125,13 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp } }, hwnd, &hPLM)) return 1; + + if (RegisterAppConstrainedChangeNotification([](BOOLEAN constrained, PVOID context) + { + // To ensure we use the main UI thread to process the notification, we self-post a message + SendMessage(reinterpret_cast(context), WM_USER + 1, (constrained) ? 1u : 0u, 0); + }, hwnd, &hPLM2)) + return 1; } // Main message loop @@ -144,13 +152,14 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp g_sample.reset(); UnregisterAppStateChangeNotification(hPLM); - + UnregisterAppConstrainedChangeNotification(hPLM2); + CloseHandle(g_plmSuspendComplete); CloseHandle(g_plmSignalResume); XGameRuntimeUninitialize(); - return (int) msg.wParam; + return static_cast(msg.wParam); } // Windows procedure @@ -168,18 +177,52 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); + + SetDisplayMode(); sample->OnResuming(); } break; + + case WM_USER + 1: + if (sample) + { + if (wParam) + { + sample->OnConstrained(); + } + else + { + SetDisplayMode(); + + sample->OnUnConstrained(); + } + } + break; } return DefWindowProc(hWnd, message, wParam, lParam); } +// HDR helper +void SetDisplayMode() noexcept +{ + if (g_sample && g_sample->RequestHDRMode()) + { + // Request HDR mode. + auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); + + g_HDRMode = (result == XDisplayHdrModeResult::Enabled); + +#ifdef _DEBUG + OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); +#endif + } +} + // Exit helper -void ExitSample() +void ExitSample() noexcept { PostQuitMessage(0); } diff --git a/Samples/Graphics/FastBlockCompress/Readme.docx b/Samples/Graphics/FastBlockCompress/Readme.docx index 99b125c..2e080bb 100644 Binary files a/Samples/Graphics/FastBlockCompress/Readme.docx and b/Samples/Graphics/FastBlockCompress/Readme.docx differ diff --git a/Samples/Graphics/FastBlockCompress/StepTimer.h b/Samples/Graphics/FastBlockCompress/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/FastBlockCompress/StepTimer.h +++ b/Samples/Graphics/FastBlockCompress/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/FastBlockCompress/pch.h b/Samples/Graphics/FastBlockCompress/pch.h index 9a3626f..fe01fea 100644 --- a/Samples/Graphics/FastBlockCompress/pch.h +++ b/Samples/Graphics/FastBlockCompress/pch.h @@ -37,8 +37,8 @@ #include -#if _GXDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GXDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -58,18 +58,26 @@ #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include +#include +#include +#include #include #include -#include -#include #include + #include #include @@ -93,7 +101,7 @@ namespace DX class com_exception : public std::exception { public: - com_exception(HRESULT hr) : result(hr) {} + com_exception(HRESULT hr) noexcept : result(hr) {} const char* what() const override { diff --git a/Samples/Graphics/GeometricExpansion/DeviceResources.cpp b/Samples/Graphics/GeometricExpansion/DeviceResources.cpp index 7d88350..2b40774 100644 --- a/Samples/Graphics/GeometricExpansion/DeviceResources.cpp +++ b/Samples/Graphics/GeometricExpansion/DeviceResources.cpp @@ -12,7 +12,6 @@ using namespace DX; using Microsoft::WRL::ComPtr; -#ifdef _GAMING_DESKTOP #ifdef __clang__ #pragma clang diagnostic ignored "-Wcovered-switch-default" #pragma clang diagnostic ignored "-Wswitch-enum" @@ -20,6 +19,7 @@ using Microsoft::WRL::ComPtr; #pragma warning(disable : 4061) +#ifdef _GAMING_DESKTOP namespace { inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) noexcept @@ -39,7 +39,8 @@ namespace DeviceResources::DeviceResources( DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, - UINT backBufferCount) noexcept(false) : + UINT backBufferCount, + unsigned int flags) noexcept(false) : m_backBufferIndex(0), m_fenceValues{}, #ifdef _GAMING_XBOX @@ -54,6 +55,7 @@ DeviceResources::DeviceResources( m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_0), m_outputSize{ 0, 0, 1, 1 }, + m_options(flags), m_deviceNotify(nullptr) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) @@ -72,7 +74,7 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } #endif } @@ -98,6 +100,14 @@ void DeviceResources::CreateDeviceResources() params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#if defined(_GAMING_XBOX_SCARLETT) && (_GRDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif + HRESULT hr = D3D12XboxCreateDevice( nullptr, ¶ms, @@ -150,7 +160,7 @@ void DeviceResources::CreateDeviceResources() 80 /* IDXGISwapChain::GetContainingOutput: The swapchain's adapter does not control the output on which the swapchain's window resides. */, }; DXGI_INFO_QUEUE_FILTER filter = {}; - filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.NumIDs = static_cast(std::size(hide)); filter.DenyList.pIDList = hide; dxgiInfoQueue->AddStorageFilterEntries(DXGI_DEBUG_DXGI, &filter); } @@ -194,9 +204,11 @@ void DeviceResources::CreateDeviceResources() // Workarounds for debug layer issues on hybrid-graphics systems D3D12_MESSAGE_ID_EXECUTECOMMANDLISTS_WRONGSWAPCHAINBUFFERREFERENCE, D3D12_MESSAGE_ID_RESOURCE_BARRIER_MISMATCHING_COMMAND_LIST_TYPE, + // Workaround for debug layer issues with mesh shader validation. + static_cast(1323) /* D3D12_MESSAGE_ID_CREATEMESHSHADER_TOPOLOGY_MISMATCH */, }; D3D12_INFO_QUEUE_FILTER filter = {}; - filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.NumIDs = static_cast(std::size(hide)); filter.DenyList.pIDList = hide; d3dInfoQueue->AddStorageFilterEntries(&filter); } @@ -205,6 +217,9 @@ void DeviceResources::CreateDeviceResources() // Determine maximum supported feature level for this device static const D3D_FEATURE_LEVEL s_featureLevels[] = { +#if defined(NTDDI_WIN10_FE) && (NTDDI_VERSION >= NTDDI_WIN10_FE) + D3D_FEATURE_LEVEL_12_2, +#endif D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, D3D_FEATURE_LEVEL_11_1, @@ -213,7 +228,7 @@ void DeviceResources::CreateDeviceResources() D3D12_FEATURE_DATA_FEATURE_LEVELS featLevels = { - _countof(s_featureLevels), s_featureLevels, D3D_FEATURE_LEVEL_11_0 + static_cast(std::size(s_featureLevels)), s_featureLevels, D3D_FEATURE_LEVEL_11_0 }; hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &featLevels, sizeof(featLevels)); @@ -284,7 +299,7 @@ void DeviceResources::CreateDeviceResources() m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { - throw std::exception("CreateEvent"); + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } #ifdef _GAMING_XBOX @@ -297,7 +312,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { if (!m_window) { - throw std::exception("Call SetWindow with a valid window handle"); + throw std::logic_error("Call SetWindow with a valid Win32 window handle"); } // Wait until all previous GPU work is complete. @@ -323,7 +338,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -355,7 +370,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -366,7 +381,7 @@ void DeviceResources::CreateWindowSizeDependentResources() #else // _GAMING_DESKTOP - DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + const DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); // If the swap chain already exists, resize it, otherwise create one. if (m_swapChain) @@ -449,7 +464,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -464,7 +479,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -477,7 +492,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -588,12 +603,6 @@ void DeviceResources::HandleDeviceLost() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { -#ifdef _GAMING_XBOX - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); -#endif - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -601,7 +610,8 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState); m_commandList->ResourceBarrier(1, &barrier); } @@ -613,7 +623,9 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); m_commandList->ResourceBarrier(1, &barrier); } @@ -633,9 +645,12 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) m_commandQueue->PresentX(1, &planeParameters, nullptr) ); - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. -#else + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + +#else // _GAMING_DESKTOP // The first argument instructs DXGI to block until VSync, putting the application // to sleep until the next VSync. This ensures we don't waste any cycles rendering @@ -658,9 +673,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) ThrowIfFailed(hr); } -#endif - MoveToNextFrame(); +#endif } // Handle GPU suspend/resume @@ -686,13 +700,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -701,32 +715,20 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() -{ - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. #ifdef _GAMING_XBOX - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; -#else - m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); -#endif - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() +{ + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } -#ifdef _GAMING_XBOX // Set frame interval and register for frame events void DeviceResources::RegisterFrameEvents() { @@ -755,7 +757,30 @@ void DeviceResources::RegisterFrameEvents() nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE)); } -#else + +#else // _GAMING_DESKTOP + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + // This method acquires the first available hardware adapter that supports Direct3D 12. // If no such adapter can be found, try WARP. Otherwise throw an exception. void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) @@ -797,7 +822,7 @@ void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) // Try WARP12 instead if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) { - throw std::exception("WARP12 not available. Enable the 'Graphics Tools' optional feature"); + throw std::runtime_error("WARP12 not available. Enable the 'Graphics Tools' optional feature"); } OutputDebugStringA("Direct3D Adapter - WARP12\n"); @@ -806,7 +831,7 @@ void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) if (!adapter) { - throw std::exception("No Direct3D 12 device found"); + throw std::runtime_error("No Direct3D 12 device found"); } *ppAdapter = adapter.Detach(); diff --git a/Samples/Graphics/GeometricExpansion/DeviceResources.h b/Samples/Graphics/GeometricExpansion/DeviceResources.h index a920f13..0e0aeb0 100644 --- a/Samples/Graphics/GeometricExpansion/DeviceResources.h +++ b/Samples/Graphics/GeometricExpansion/DeviceResources.h @@ -22,9 +22,13 @@ namespace DX class DeviceResources { public: + static constexpr unsigned int c_ReverseDepth = 0x1; + static constexpr unsigned int c_AmplificationShaders = 0x2; + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, - UINT backBufferCount = 2) noexcept(false); + UINT backBufferCount = 2, + unsigned int flags = 0) noexcept(false); ~DeviceResources(); DeviceResources(DeviceResources&&) = default; @@ -45,6 +49,9 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; +#ifdef _GAMING_XBOX + void WaitForOrigin(); +#endif // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -68,6 +75,7 @@ namespace DX D3D12_RECT GetScissorRect() const noexcept { return m_scissorRect; } UINT GetCurrentFrameIndex() const noexcept { return m_backBufferIndex; } UINT GetBackBufferCount() const noexcept { return m_backBufferCount; } + unsigned int GetDeviceOptions() const noexcept { return m_options; } CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const noexcept { @@ -81,10 +89,10 @@ namespace DX } private: - void MoveToNextFrame(); #ifdef _GAMING_XBOX void RegisterFrameEvents(); #else + void MoveToNextFrame(); void GetAdapter(IDXGIAdapter1** ppAdapter); #endif @@ -131,6 +139,9 @@ namespace DX D3D_FEATURE_LEVEL m_d3dFeatureLevel; RECT m_outputSize; + // DeviceResources options (see flags above) + unsigned int m_options; + // The IDeviceNotify can be held directly as it owns the DeviceResources. IDeviceNotify* m_deviceNotify; }; diff --git a/Samples/Graphics/GeometricExpansion/GeometricExpansion.cpp b/Samples/Graphics/GeometricExpansion/GeometricExpansion.cpp index a9e346a..8cbe26a 100644 --- a/Samples/Graphics/GeometricExpansion/GeometricExpansion.cpp +++ b/Samples/Graphics/GeometricExpansion/GeometricExpansion.cpp @@ -15,7 +15,7 @@ #pragma warning( disable : 4324 4365 ) -extern void ExitSample(); +extern void ExitSample() noexcept; using namespace ATG; using namespace DirectX; @@ -47,20 +47,10 @@ namespace constexpr float c_springCoeff = 4.0f; constexpr float c_dragFactor = 1.0f; constexpr float c_initialSpeed = 3.0f; - -#ifdef _GAMING_DESKTOP - static const GUID D3D12ExperimentalShaderModelsID = { /* 76f5573e-f13a-40f5-b297-81ce9e18933f */ - 0x76f5573e, - 0xf13a, - 0x40f5, - { 0xb2, 0x97, 0x81, 0xce, 0x9e, 0x18, 0x93, 0x3f } - }; -#endif } Sample::Sample() noexcept(false) - : m_deviceResources(std::make_unique()) - , m_displayWidth(0) + : m_displayWidth(0) , m_displayHeight(0) , m_frame(0) , m_spawnRate(c_spawnRate) @@ -76,6 +66,7 @@ Sample::Sample() noexcept(false) ValueRange(c_minLifetime, c_maxLifetime), ValueRange(c_minSize, c_maxSize)) { + m_deviceResources = std::make_unique(); m_deviceResources->RegisterDeviceNotify(this); } @@ -90,12 +81,10 @@ Sample::~Sample() // Initialize the Direct3D resources required to run. void Sample::Initialize(HWND window, int width, int height) { -#ifdef _GAMING_DESKTOP - D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModelsID, nullptr, nullptr); -#endif - m_gamePad = std::make_unique(); + m_keyboard = std::make_unique(); + m_mouse = std::make_unique(); m_mouse->SetWindow(window); @@ -114,6 +103,10 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); +#ifdef _GAMING_XBOX + m_deviceResources->WaitForOrigin(); +#endif + m_timer.Tick([&]() { Update(m_timer); @@ -283,8 +276,8 @@ void Sample::Render() auto commandList = m_deviceResources->GetCommandList(); PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); - ID3D12DescriptorHeap* heaps[] = { m_srvPile->Heap() }; - commandList->SetDescriptorHeaps(1, heaps); + auto heaps = m_srvPile->Heap(); + commandList->SetDescriptorHeaps(1, &heaps); m_particleSystem.Draw(commandList, m_graphicsMemory.get()); @@ -306,16 +299,16 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -326,7 +319,7 @@ void Sample::DrawHUD(ID3D12GraphicsCommandList* commandList) { m_hudBatch->Begin(commandList); - auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(m_displayWidth, m_displayHeight); + auto const safe = SimpleMath::Viewport::ComputeTitleSafeArea(m_displayWidth, m_displayHeight); wchar_t textBuffer[128] = {}; XMFLOAT2 textPos = XMFLOAT2(float(safe.left), float(safe.top)); @@ -398,14 +391,6 @@ void Sample::DrawHUD(ID3D12GraphicsCommandList* commandList) #pragma region Message Handlers // Message handlers -void Sample::OnActivated() -{ -} - -void Sample::OnDeactivated() -{ -} - void Sample::OnSuspending() { m_deviceResources->Suspend(); @@ -421,7 +406,7 @@ void Sample::OnResuming() void Sample::OnWindowMoved() { - auto r = m_deviceResources->GetOutputSize(); + auto const r = m_deviceResources->GetOutputSize(); m_deviceResources->WindowSizeChanged(r.right, r.bottom); } @@ -434,7 +419,7 @@ void Sample::OnWindowSizeChanged(int width, int height) } // Properties -void Sample::GetDefaultSize(int& width, int& height) const +void Sample::GetDefaultSize(int& width, int& height) const noexcept { width = 1280; height = 720; @@ -469,8 +454,6 @@ void Sample::CreateDeviceDependentResources() // Create heap m_srvPile = std::make_unique(device, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 128, DescriptorHeapIndex::SRV_Count); @@ -480,7 +463,7 @@ void Sample::CreateDeviceDependentResources() resourceUpload.Begin(); // HUD - auto backBufferRts = RenderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState backBufferRts(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); auto spritePSD = SpriteBatchPipelineStateDescription(backBufferRts, &CommonStates::AlphaBlend); m_hudBatch = std::make_unique(device, resourceUpload, spritePSD); @@ -503,7 +486,7 @@ void Sample::CreateDeviceDependentResources() // Allocate all memory resources that change on a window SizeChanged event. void Sample::CreateWindowSizeDependentResources() { - RECT size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); m_displayWidth = size.right - size.left; m_displayHeight = size.bottom - size.top; @@ -524,6 +507,11 @@ void Sample::CreateWindowSizeDependentResources() void Sample::OnDeviceLost() { + m_particleSystem.ReleaseDevice(); + m_hudBatch.reset(); + m_smallFont.reset(); + m_ctrlFont.reset(); + m_srvPile.reset(); m_graphicsMemory.reset(); } diff --git a/Samples/Graphics/GeometricExpansion/GeometricExpansion.h b/Samples/Graphics/GeometricExpansion/GeometricExpansion.h index 9d212bd..e49ec0f 100644 --- a/Samples/Graphics/GeometricExpansion/GeometricExpansion.h +++ b/Samples/Graphics/GeometricExpansion/GeometricExpansion.h @@ -20,6 +20,12 @@ public: Sample() noexcept(false); ~Sample(); + Sample(Sample&&) = default; + Sample& operator= (Sample&&) = default; + + Sample(Sample const&) = delete; + Sample& operator= (Sample const&) = delete; + // Initialization and management void Initialize(HWND window, int width, int height); @@ -31,15 +37,15 @@ public: void OnDeviceRestored() override; // Messages - void OnActivated(); - void OnDeactivated(); + void OnActivated() {} + void OnDeactivated() {} void OnSuspending(); void OnResuming(); void OnWindowMoved(); void OnWindowSizeChanged(int width, int height); // Properties - void GetDefaultSize(int& width, int& height) const; + void GetDefaultSize(int& width, int& height) const noexcept; private: void Update(DX::StepTimer const& timer); diff --git a/Samples/Graphics/GeometricExpansion/Main.cpp b/Samples/Graphics/GeometricExpansion/Main.cpp index 4f935eb..a3e3743 100644 --- a/Samples/Graphics/GeometricExpansion/Main.cpp +++ b/Samples/Graphics/GeometricExpansion/Main.cpp @@ -20,6 +20,13 @@ using namespace DirectX; +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +#pragma warning(disable : 4061) + namespace { std::unique_ptr g_sample; @@ -27,11 +34,12 @@ namespace HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; #endif -}; +} LPCWSTR g_szAppName = L"GeometricExpansion"; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void ExitSample() noexcept; // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) @@ -55,7 +63,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp if (hr == E_GAMERUNTIME_DLL_NOT_FOUND || hr == E_GAMERUNTIME_VERSION_MISMATCH) { #ifdef _GAMING_DESKTOP - (void)MessageBoxW(nullptr, L"Game Runtime is not installed on this system or needs updating.", g_szAppName, MB_ICONERROR | MB_OK); + std::ignore = MessageBoxW(nullptr, L"Game Runtime is not installed on this system or needs updating.", g_szAppName, MB_ICONERROR | MB_OK); #endif } return 1; @@ -80,7 +88,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); wcex.lpszClassName = L"GeometricExpansionWindowClass"; if (!RegisterClassExW(&wcex)) return 1; @@ -134,7 +142,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -164,14 +172,14 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp #ifdef _GAMING_XBOX UnregisterAppStateChangeNotification(hPLM); - + CloseHandle(g_plmSuspendComplete); CloseHandle(g_plmSignalResume); #endif XGameRuntimeUninitialize(); - return (int) msg.wParam; + return static_cast(msg.wParam); } // Windows procedure @@ -232,7 +240,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); sample->OnResuming(); } @@ -246,7 +254,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) else { PAINTSTRUCT ps; - (void)BeginPaint(hWnd, &ps); + std::ignore = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); } break; @@ -298,12 +306,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_GETMINMAXINFO: - { - auto info = reinterpret_cast(lParam); - info->ptMinTrackSize.x = 320; - info->ptMinTrackSize.y = 200; - } - break; + if (lParam) + { + auto info = reinterpret_cast(lParam); + info->ptMinTrackSize.x = 320; + info->ptMinTrackSize.y = 200; + } + break; case WM_POWERBROADCAST: switch (wParam) @@ -360,7 +369,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); @@ -388,7 +397,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } // Exit helper -void ExitSample() +void ExitSample() noexcept { PostQuitMessage(0); } diff --git a/Samples/Graphics/GeometricExpansion/Particles.cpp b/Samples/Graphics/GeometricExpansion/Particles.cpp index 4701627..dd4ccf1 100644 --- a/Samples/Graphics/GeometricExpansion/Particles.cpp +++ b/Samples/Graphics/GeometricExpansion/Particles.cpp @@ -10,6 +10,7 @@ #pragma warning( disable : 4324 4365 ) +using namespace ATG; using namespace DirectX; using namespace DirectX::SimpleMath; @@ -45,220 +46,228 @@ namespace } } -namespace ATG +ParticleSystem::ParticleSystem( + FXMVECTOR position, + float spawnRate, + float springCoeff, + float dragFactor, + float speed, + ValueRange lifetime, + ValueRange size) + : m_position{} + , m_spawnFrequency(1.0f / spawnRate) + , m_springCoeff(springCoeff) + , m_dragFactor(dragFactor) + , m_simulationTime(0.0f) + , m_speed(speed) + , m_angle(XM_2PI) + , m_lifetime(lifetime) + , m_size(size) + , m_particles{} { - ParticleSystem::ParticleSystem( - FXMVECTOR position, - float spawnRate, - float springCoeff, - float dragFactor, - float speed, - ValueRange lifetime, - ValueRange size) - : m_position{} - , m_spawnFrequency(1.0f / spawnRate) - , m_springCoeff(springCoeff) - , m_dragFactor(dragFactor) - , m_simulationTime(0.0f) - , m_speed(speed) - , m_angle(XM_2PI) - , m_lifetime(lifetime) - , m_size(size) - , m_particles{} - { - assert(spawnRate > 0.0f); + assert(spawnRate > 0.0f); - XMStoreFloat3(&m_position, position); - m_particles.reserve(c_particleBufferInitSize); // Prime particle list with arbitrarily large allocation - } - - void ParticleSystem::CreateResources(DX::DeviceResources& deviceResources) - { - m_device = deviceResources.GetD3DDevice(); - - auto heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); - auto cbDesc = CD3DX12_RESOURCE_DESC::Buffer(GetAlignedSize(sizeof(Constants))); - - DX::ThrowIfFailed(m_device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &cbDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_GRAPHICS_PPV_ARGS(m_constantBuffer.ReleaseAndGetAddressOf()))); - - ReloadPipelineState(deviceResources); - } - - void ParticleSystem::Update(float dt, const Matrix& view, const Matrix& proj) - { - m_simulationTime += dt; - - // Kill dead particles - for (size_t i = 0; i < m_particles.size(); ++i) - { - auto& p = m_particles[i]; - - if (m_simulationTime - p.InitTime > p.Lifetime) - { - if (i != m_particles.size() - 1) - { - // Just overwrite it with the last particle and continue. - p = m_particles.back(); - --i; - } - - m_particles.pop_back(); - } - } - - // Spawn new particles - float lastSpawnTime = floorf((m_simulationTime - dt) / m_spawnFrequency) * m_spawnFrequency; - - size_t newCount = static_cast(floorf((m_simulationTime - lastSpawnTime) / m_spawnFrequency)); - size_t oldCount = m_particles.size(); - - m_particles.resize(oldCount + newCount); - - // Initialize new particles - for (size_t i = oldCount; i < m_particles.size(); ++i) - { - float angle = m_angle.Gen(); // Set off in random direction in xz plane - Vector3 direction(cosf(angle), 0, sinf(angle)); - - Vector3 velocity; - velocity = direction * m_speed; // Random speed in xz - velocity.y = m_speed; // Initial kick in y to break equilibrium - - auto& p = m_particles[i]; - p.Position = m_position; - p.Velocity = velocity; - p.InitTime = m_simulationTime; - p.Lifetime = m_lifetime.Gen(); - p.Size = m_size.Gen(); - } - - // Perform integration at fixed time intervals for stability - for (auto& p : m_particles) - { - // Simulate particles over dt using a fixed timestep - for (float accum = dt; accum >= 0; accum -= c_fixedStep) - { - // Only compute drag for horizontal velocity - Vector3 velXZ = p.Velocity; - velXZ.y = 0; - - float length = velXZ.Length(); - Vector3 direction = velXZ / length; - - // Compute forces - Vector3 force; - force.y = -m_springCoeff * (p.Position.y - m_position.y); // Spring force proportional to displacement in y from rest position - force.x = -m_dragFactor * c_dragCoeff * length * direction.x; // Drag force proportional to velocity in xz - force.z = -m_dragFactor * c_dragCoeff * length * direction.z; - - Vector3 acceleration = force * c_particleMassInv; - - // Perform integration - float stepSize = std::min(accum, c_fixedStep); - - p.Velocity = p.Velocity + acceleration * stepSize; - p.Position = p.Position + p.Velocity * stepSize; - } - } - - // Update constants - m_constants.ViewProj = (view * proj).Transpose(); - m_constants.ViewPosition = Vector3::Transform(Vector3::Zero, view.Invert()); - m_constants.ParticleCount = static_cast(m_particles.size()); - m_constants.CameraUp = Vector3::TransformNormal(Vector3::Up, view.Invert()); - m_constants.SimulationTime = m_simulationTime; - XMStoreFloat3(&m_constants.Color, DirectX::Colors::Red); - - // Update GPU Buffers - TryResizeBuffers(); - } - - void ParticleSystem::Draw(ID3D12GraphicsCommandList6* commandList, GraphicsMemory* graphicsMemory) - { - // Copy cpu memory to upload buffer - auto upload = graphicsMemory->Allocate(GetAlignedSize(sizeof(Constants)) + m_particles.size() * sizeof(Particle)); - - std::memcpy(static_cast(upload.Memory()), &m_constants, sizeof(Constants)); - std::memcpy(static_cast(upload.Memory()) + GetAlignedSize(sizeof(Constants)), m_particles.data(), m_particles.size() * sizeof(Particle)); - - // Copy from upload buffer to resource - DirectX::TransitionResource(commandList, m_particleBuffer.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_COPY_DEST); - DirectX::TransitionResource(commandList, m_constantBuffer.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_COPY_DEST); - - commandList->CopyBufferRegion(m_constantBuffer.Get(), 0, upload.Resource(), 0, sizeof(Constants)); - commandList->CopyBufferRegion(m_particleBuffer.Get(), 0, upload.Resource(), GetAlignedSize(sizeof(Constants)), m_particles.size() * sizeof(Particle)); - - DirectX::TransitionResource(commandList, m_particleBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ); - DirectX::TransitionResource(commandList, m_constantBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ); - - // Draw - commandList->SetGraphicsRootSignature(m_rootSignature.Get()); - commandList->SetPipelineState(m_particlePSO.Get()); - - commandList->SetGraphicsRootConstantBufferView(0, m_constantBuffer->GetGPUVirtualAddress()); - commandList->SetGraphicsRootShaderResourceView(1, m_particleBuffer->GetGPUVirtualAddress()); - - auto count = RoundUpDiv((uint32_t)m_particles.size(), GROUP_SIZE / 4u); - commandList->DispatchMesh(count, 1, 1); - } - - void ParticleSystem::ReloadPipelineState(DX::DeviceResources& deviceResources) - { - auto device = deviceResources.GetD3DDevice(); - - auto meshShader = DX::ReadData(s_meshShaderFilename); - auto pixelShader = DX::ReadData(s_pixelShaderFilename); - - DX::ThrowIfFailed(device->CreateRootSignature(0, meshShader.data(), meshShader.size(), IID_GRAPHICS_PPV_ARGS(m_rootSignature.ReleaseAndGetAddressOf()))); - - D3DX12_MESH_SHADER_PIPELINE_STATE_DESC psoDesc = {}; - psoDesc.pRootSignature = m_rootSignature.Get(); - psoDesc.MS = { meshShader.data(), meshShader.size() }; - psoDesc.PS = { pixelShader.data(), pixelShader.size() }; - psoDesc.NumRenderTargets = 1; - psoDesc.RTVFormats[0] = deviceResources.GetBackBufferFormat(); - psoDesc.DSVFormat = deviceResources.GetDepthBufferFormat(); - psoDesc.RasterizerState = CommonStates::CullNone; - psoDesc.BlendState = CommonStates::AlphaBlend; - psoDesc.DepthStencilState = CommonStates::DepthRead; - psoDesc.SampleMask = UINT_MAX; - psoDesc.SampleDesc = DefaultSampleDesc(); - - auto meshStreamDesc = CD3DX12_PIPELINE_MESH_STATE_STREAM(psoDesc); - - D3D12_PIPELINE_STATE_STREAM_DESC streamDesc = {}; - streamDesc.SizeInBytes = sizeof(meshStreamDesc); - streamDesc.pPipelineStateSubobjectStream = &meshStreamDesc; - - DX::ThrowIfFailed(device->CreatePipelineState(&streamDesc, IID_GRAPHICS_PPV_ARGS(m_particlePSO.ReleaseAndGetAddressOf()))); - } - - void ParticleSystem::TryResizeBuffers() - { - assert(m_device != nullptr); - - const size_t minSize = sizeof(Particle) * c_particleBufferInitSize; - - size_t newSize = m_particles.size() * sizeof(Particle) * 2; // Over-allocate by two to reduce number of allocations - newSize = std::max(newSize, minSize); - - m_particleBufferTemp = nullptr; // Release the old particle buffer, which we cached for a frame to avoid read after release - - // Don't resize if it's beneath our high watermark - if (m_particleBuffer != nullptr) - { - if (newSize < m_particleBuffer->GetDesc().Width) - { - return; - } - } - - m_particleBufferTemp = m_particleBuffer; // Temporarily cache the old particle buffer to avoid releasing before its last usage is complete. - - // Reallocate particle buffer - auto heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); - auto particleDesc = CD3DX12_RESOURCE_DESC::Buffer(GetAlignedSize(newSize)); - - DX::ThrowIfFailed(m_device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &particleDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_GRAPHICS_PPV_ARGS(m_particleBuffer.ReleaseAndGetAddressOf()))); - } + XMStoreFloat3(&m_position, position); + m_particles.reserve(c_particleBufferInitSize); // Prime particle list with arbitrarily large allocation +} + +void ParticleSystem::CreateResources(DX::DeviceResources& deviceResources) +{ + m_device = deviceResources.GetD3DDevice(); + + const CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_DEFAULT); + auto cbDesc = CD3DX12_RESOURCE_DESC::Buffer(GetAlignedSize(sizeof(Constants))); + + DX::ThrowIfFailed(m_device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &cbDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_GRAPHICS_PPV_ARGS(m_constantBuffer.ReleaseAndGetAddressOf()))); + + ReloadPipelineState(deviceResources); +} + +void ParticleSystem::ReleaseDevice() +{ + m_rootSignature.Reset(); + m_particlePSO.Reset(); + m_constantBuffer.Reset(); + m_particleBuffer.Reset(); + m_particleBufferTemp.Reset(); + m_device.Reset(); +} + + +void ParticleSystem::Update(float dt, const Matrix& view, const Matrix& proj) +{ + m_simulationTime += dt; + + // Kill dead particles + for (size_t i = 0; i < m_particles.size(); ++i) + { + auto& p = m_particles[i]; + + if (m_simulationTime - p.InitTime > p.Lifetime) + { + if (i != m_particles.size() - 1) + { + // Just overwrite it with the last particle and continue. + p = m_particles.back(); + --i; + } + + m_particles.pop_back(); + } + } + + // Spawn new particles + float lastSpawnTime = floorf((m_simulationTime - dt) / m_spawnFrequency) * m_spawnFrequency; + + size_t newCount = static_cast(floorf((m_simulationTime - lastSpawnTime) / m_spawnFrequency)); + size_t oldCount = m_particles.size(); + + m_particles.resize(oldCount + newCount); + + // Initialize new particles + for (size_t i = oldCount; i < m_particles.size(); ++i) + { + float angle = m_angle.Gen(); // Set off in random direction in xz plane + Vector3 direction(cosf(angle), 0, sinf(angle)); + + Vector3 velocity; + velocity = direction * m_speed; // Random speed in xz + velocity.y = m_speed; // Initial kick in y to break equilibrium + + auto& p = m_particles[i]; + p.Position = m_position; + p.Velocity = velocity; + p.InitTime = m_simulationTime; + p.Lifetime = m_lifetime.Gen(); + p.Size = m_size.Gen(); + } + + // Perform integration at fixed time intervals for stability + for (auto& p : m_particles) + { + // Simulate particles over dt using a fixed timestep + for (float accum = dt; accum >= 0; accum -= c_fixedStep) + { + // Only compute drag for horizontal velocity + Vector3 velXZ = p.Velocity; + velXZ.y = 0; + + float length = velXZ.Length(); + Vector3 direction = velXZ / length; + + // Compute forces + Vector3 force; + force.y = -m_springCoeff * (p.Position.y - m_position.y); // Spring force proportional to displacement in y from rest position + force.x = -m_dragFactor * c_dragCoeff * length * direction.x; // Drag force proportional to velocity in xz + force.z = -m_dragFactor * c_dragCoeff * length * direction.z; + + Vector3 acceleration = force * c_particleMassInv; + + // Perform integration + float stepSize = std::min(accum, c_fixedStep); + + p.Velocity = p.Velocity + acceleration * stepSize; + p.Position = p.Position + p.Velocity * stepSize; + } + } + + // Update constants + m_constants.ViewProj = (view * proj).Transpose(); + m_constants.ViewPosition = Vector3::Transform(Vector3::Zero, view.Invert()); + m_constants.ParticleCount = static_cast(m_particles.size()); + m_constants.CameraUp = Vector3::TransformNormal(Vector3::Up, view.Invert()); + m_constants.SimulationTime = m_simulationTime; + XMStoreFloat3(&m_constants.Color, DirectX::Colors::Red); + + // Update GPU Buffers + TryResizeBuffers(); +} + +void ParticleSystem::Draw(ID3D12GraphicsCommandList6* commandList, GraphicsMemory* graphicsMemory) +{ + // Copy cpu memory to upload buffer + auto upload = graphicsMemory->Allocate(GetAlignedSize(sizeof(Constants)) + m_particles.size() * sizeof(Particle)); + + std::memcpy(static_cast(upload.Memory()), &m_constants, sizeof(Constants)); + std::memcpy(static_cast(upload.Memory()) + GetAlignedSize(sizeof(Constants)), m_particles.data(), m_particles.size() * sizeof(Particle)); + + // Copy from upload buffer to resource + DirectX::TransitionResource(commandList, m_particleBuffer.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_COPY_DEST); + DirectX::TransitionResource(commandList, m_constantBuffer.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_COPY_DEST); + + commandList->CopyBufferRegion(m_constantBuffer.Get(), 0, upload.Resource(), 0, sizeof(Constants)); + commandList->CopyBufferRegion(m_particleBuffer.Get(), 0, upload.Resource(), GetAlignedSize(sizeof(Constants)), m_particles.size() * sizeof(Particle)); + + DirectX::TransitionResource(commandList, m_particleBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ); + DirectX::TransitionResource(commandList, m_constantBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ); + + // Draw + commandList->SetGraphicsRootSignature(m_rootSignature.Get()); + commandList->SetPipelineState(m_particlePSO.Get()); + + commandList->SetGraphicsRootConstantBufferView(0, m_constantBuffer->GetGPUVirtualAddress()); + commandList->SetGraphicsRootShaderResourceView(1, m_particleBuffer->GetGPUVirtualAddress()); + + auto count = RoundUpDiv((uint32_t)m_particles.size(), GROUP_SIZE / 4u); + commandList->DispatchMesh(count, 1, 1); +} + +void ParticleSystem::ReloadPipelineState(DX::DeviceResources& deviceResources) +{ + auto device = deviceResources.GetD3DDevice(); + + auto meshShader = DX::ReadData(s_meshShaderFilename); + auto pixelShader = DX::ReadData(s_pixelShaderFilename); + + DX::ThrowIfFailed(device->CreateRootSignature(0, meshShader.data(), meshShader.size(), IID_GRAPHICS_PPV_ARGS(m_rootSignature.ReleaseAndGetAddressOf()))); + + D3DX12_MESH_SHADER_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.pRootSignature = m_rootSignature.Get(); + psoDesc.MS = { meshShader.data(), meshShader.size() }; + psoDesc.PS = { pixelShader.data(), pixelShader.size() }; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = deviceResources.GetBackBufferFormat(); + psoDesc.DSVFormat = deviceResources.GetDepthBufferFormat(); + psoDesc.RasterizerState = CommonStates::CullNone; + psoDesc.BlendState = CommonStates::AlphaBlend; + psoDesc.DepthStencilState = CommonStates::DepthRead; + psoDesc.SampleMask = UINT_MAX; + psoDesc.SampleDesc = DefaultSampleDesc(); + + auto meshStreamDesc = CD3DX12_PIPELINE_MESH_STATE_STREAM(psoDesc); + + D3D12_PIPELINE_STATE_STREAM_DESC streamDesc = {}; + streamDesc.SizeInBytes = sizeof(meshStreamDesc); + streamDesc.pPipelineStateSubobjectStream = &meshStreamDesc; + + DX::ThrowIfFailed(device->CreatePipelineState(&streamDesc, IID_GRAPHICS_PPV_ARGS(m_particlePSO.ReleaseAndGetAddressOf()))); +} + +void ParticleSystem::TryResizeBuffers() +{ + assert(m_device != nullptr); + + constexpr size_t minSize = sizeof(Particle) * c_particleBufferInitSize; + + size_t newSize = m_particles.size() * sizeof(Particle) * 2; // Over-allocate by two to reduce number of allocations + newSize = std::max(newSize, minSize); + + m_particleBufferTemp = nullptr; // Release the old particle buffer, which we cached for a frame to avoid read after release + + // Don't resize if it's beneath our high watermark + if (m_particleBuffer != nullptr) + { + if (newSize < m_particleBuffer->GetDesc().Width) + { + return; + } + } + + m_particleBufferTemp = m_particleBuffer; // Temporarily cache the old particle buffer to avoid releasing before its last usage is complete. + + // Reallocate particle buffer + const CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_DEFAULT); + auto particleDesc = CD3DX12_RESOURCE_DESC::Buffer(GetAlignedSize(newSize)); + + DX::ThrowIfFailed(m_device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &particleDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_GRAPHICS_PPV_ARGS(m_particleBuffer.ReleaseAndGetAddressOf()))); } diff --git a/Samples/Graphics/GeometricExpansion/Particles.h b/Samples/Graphics/GeometricExpansion/Particles.h index 54cfc44..bd3a620 100644 --- a/Samples/Graphics/GeometricExpansion/Particles.h +++ b/Samples/Graphics/GeometricExpansion/Particles.h @@ -42,6 +42,17 @@ namespace ATG ValueRange size ); + ~ParticleSystem() + { + ReleaseDevice(); + } + + ParticleSystem(ParticleSystem&&) = default; + ParticleSystem& operator= (ParticleSystem&&) = default; + + ParticleSystem(ParticleSystem const&) = delete; + ParticleSystem& operator= (ParticleSystem const&) = delete; + void SetSpawnRate(float spawnRate) { m_spawnFrequency = 1.0f / std::max(1e-4f, spawnRate); } void SetSpringCoefficent(float coeff) { m_springCoeff = std::max(1e-4f, coeff); } void SetDragFactor(float factor) { m_dragFactor = std::max(0.0f, factor); } @@ -49,6 +60,7 @@ namespace ATG void CreateResources(DX::DeviceResources& deviceResources); void ReloadPipelineState(DX::DeviceResources& deviceResources); + void ReleaseDevice(); void Update(float deltaTime, const DirectX::SimpleMath::Matrix& view, const DirectX::SimpleMath::Matrix& proj); void Draw(ID3D12GraphicsCommandList6* commandList, DirectX::GraphicsMemory* graphicsMemory); @@ -73,7 +85,7 @@ namespace ATG std::vector m_particles; // D3D12 API Objects - ID3D12Device* m_device; + Microsoft::WRL::ComPtr m_device; Microsoft::WRL::ComPtr m_rootSignature; Microsoft::WRL::ComPtr m_particlePSO; diff --git a/Samples/Graphics/GeometricExpansion/ReadMe.docx b/Samples/Graphics/GeometricExpansion/ReadMe.docx index ff1ddda..15c11b9 100644 Binary files a/Samples/Graphics/GeometricExpansion/ReadMe.docx and b/Samples/Graphics/GeometricExpansion/ReadMe.docx differ diff --git a/Samples/Graphics/GeometricExpansion/StepTimer.h b/Samples/Graphics/GeometricExpansion/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/GeometricExpansion/StepTimer.h +++ b/Samples/Graphics/GeometricExpansion/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/GeometricExpansion/pch.h b/Samples/Graphics/GeometricExpansion/pch.h index a80e9b3..638798f 100644 --- a/Samples/Graphics/GeometricExpansion/pch.h +++ b/Samples/Graphics/GeometricExpansion/pch.h @@ -41,8 +41,8 @@ #include -#if _GRDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GRDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -69,14 +69,20 @@ #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include - -#include -#include +#include +#include +#include #ifdef _GAMING_XBOX #include @@ -89,7 +95,6 @@ #include #include "CommonStates.h" -#include "ControllerFont.h" #include "DescriptorHeap.h" #include "DirectXHelpers.h" #include "GamePad.h" @@ -97,21 +102,23 @@ #include "Keyboard.h" #include "Model.h" #include "Mouse.h" -#include "OrbitCamera.h" -#include "ReadData.h" #include "RenderTargetState.h" #include "ResourceUploadBatch.h" #include "SimpleMath.h" #include "SpriteBatch.h" #include "SpriteFont.h" +#include "ControllerFont.h" +#include "OrbitCamera.h" +#include "ReadData.h" + namespace DX { // Helper class for COM exceptions class com_exception : public std::exception { public: - com_exception(HRESULT hr) : result(hr) {} + com_exception(HRESULT hr) noexcept : result(hr) {} const char* what() const override { diff --git a/Samples/Graphics/HDR10/DeviceResources.cpp b/Samples/Graphics/HDR10/DeviceResources.cpp index 233948e..836bf26 100644 --- a/Samples/Graphics/HDR10/DeviceResources.cpp +++ b/Samples/Graphics/HDR10/DeviceResources.cpp @@ -1,6 +1,8 @@ // // DeviceResources.cpp - A wrapper for the Direct3D 12.X device and swapchain // +// Explicit HDR10+GameDVR rendering variant. +// #include "pch.h" #include "DeviceResources.h" @@ -55,12 +57,16 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } } // Configures the Direct3D device, and stores handles to it and the device context. +#ifdef _GAMING_XBOX_SCARLETT +void DeviceResources::CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags) +#else void DeviceResources::CreateDeviceResources() +#endif { // Create the DX12 API device object. D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; @@ -77,6 +83,17 @@ void DeviceResources::CreateDeviceResources() params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#ifdef _GAMING_XBOX_SCARLETT + params.CreateDeviceFlags = createDeviceFlags; + +#if (_GXDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif +#endif HRESULT hr = D3D12XboxCreateDevice( nullptr, @@ -223,7 +240,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -255,7 +272,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -283,7 +300,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_gameDVRFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(m_backBufferCount + n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargetsGameDVR[n].Get(), &rtvDesc, rtvDescriptorGameDVR); @@ -297,7 +314,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -310,7 +327,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -346,10 +363,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -359,7 +372,7 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ // Transition the render target into the correct state to allow for drawing into it. if (m_options & c_EnableHDR) { - D3D12_RESOURCE_BARRIER barriers[2] = + const D3D12_RESOURCE_BARRIER barriers[2] = { CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState), @@ -370,7 +383,8 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ } else { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState); m_commandList->ResourceBarrier(1, &barrier); } @@ -385,7 +399,7 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const // Transition the render target to the state that allows it to be presented to the display. if (m_options & c_EnableHDR) { - D3D12_RESOURCE_BARRIER barriers[2] = + const D3D12_RESOURCE_BARRIER barriers[2] = { CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), @@ -394,7 +408,9 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const } else { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); m_commandList->ResourceBarrier(1, &barrier); } } @@ -427,9 +443,10 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const ); } - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -451,13 +468,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -466,25 +483,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/Graphics/HDR10/DeviceResources.h b/Samples/Graphics/HDR10/DeviceResources.h index e6d4603..57241bb 100644 --- a/Samples/Graphics/HDR10/DeviceResources.h +++ b/Samples/Graphics/HDR10/DeviceResources.h @@ -1,6 +1,8 @@ // // DeviceResources.h - A wrapper for the Direct3D 12.X device and swapchain // +// Explicit HDR10+GameDVR rendering variant. +// #pragma once @@ -10,9 +12,11 @@ namespace DX class DeviceResources { public: - static constexpr unsigned int c_Enable4K_UHD = 0x1; - static constexpr unsigned int c_EnableQHD = 0x2; - static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_ReverseDepth = 0x8; + static constexpr unsigned int c_AmplificationShaders = 0x10; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -26,7 +30,11 @@ namespace DX DeviceResources(DeviceResources const&) = delete; DeviceResources& operator= (DeviceResources const&) = delete; +#ifdef _GAMING_XBOX_SCARLETT + void CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags = D3D12XBOX_CREATE_DEVICE_FLAG_NONE); +#else void CreateDeviceResources(); +#endif void CreateWindowSizeDependentResources(); void SetWindow(HWND window) noexcept { m_window = window; } void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT, @@ -36,6 +44,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -69,8 +78,8 @@ namespace DX } // Direct3D HDR Game DVR support for Xbox One. - ID3D12Resource* GetGameDVRRenderTarget() const noexcept { return m_renderTargetsGameDVR[m_backBufferIndex].Get(); } - DXGI_FORMAT GetGameDVRFormat() const noexcept { return m_gameDVRFormat; } + ID3D12Resource* GetGameDVRRenderTarget() const noexcept { return m_renderTargetsGameDVR[m_backBufferIndex].Get(); } + DXGI_FORMAT GetGameDVRFormat() const noexcept { return m_gameDVRFormat; } CD3DX12_CPU_DESCRIPTOR_HANDLE GetGameDVRRenderTargetView() const noexcept { @@ -80,7 +89,6 @@ namespace DX } private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; diff --git a/Samples/Graphics/HDR10/HDR10.cpp b/Samples/Graphics/HDR10/HDR10.cpp index c699dee..b84dfe0 100644 --- a/Samples/Graphics/HDR10/HDR10.cpp +++ b/Samples/Graphics/HDR10/HDR10.cpp @@ -66,23 +66,27 @@ using DirectX::Colors::White; namespace { - inline DirectX::XMVECTOR MakeColor(float value) { DirectX::XMVECTORF32 color = { value, value, value, 1.0f }; return color; } + inline XMVECTOR MakeColor(float value) noexcept + { + XMVECTORF32 color = { value, value, value, 1.0f }; + return color; + } // Clamp value between 0 and 1 - inline float Clamp(float value) + inline float Clamp(float value) noexcept { return std::min(std::max(value, 0.0f), 1.0f); } // Applies the sRGB gamma curve to a linear value. This function is only used to output UI values - float LinearToSRGB(float hdrSceneValue) + float LinearToSRGB(float hdrSceneValue) noexcept { - const float Cutoff = 0.0031308f; - const float Linear = 12.92f; - const float Scale = 1.055f; - const float Bias = 0.055f; - const float Gamma = 2.4f; - const float InvGamma = 1.0f / Gamma; + constexpr float Cutoff = 0.0031308f; + constexpr float Linear = 12.92f; + constexpr float Scale = 1.055f; + constexpr float Bias = 0.055f; + constexpr float Gamma = 2.4f; + constexpr float InvGamma = 1.0f / Gamma; // clamp values [0..1] hdrSceneValue = Clamp(hdrSceneValue); @@ -151,6 +155,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); @@ -210,10 +216,10 @@ void Sample::Update(DX::StepTimer const& timer) m_HDR10Data.PaperWhiteNits = std::min(m_HDR10Data.PaperWhiteNits, DX::c_MaxNitsFor2084); } - const float c_fastNitsDelta = 25.0f; - const float c_slowNitsDelta = 1.0f; - const float c_fastSceneValueDelta = 0.05f; - const float c_slowSceneValueDelta = 0.005f; + constexpr float c_fastNitsDelta = 25.0f; + constexpr float c_slowNitsDelta = 1.0f; + constexpr float c_fastSceneValueDelta = 0.05f; + constexpr float c_slowSceneValueDelta = 0.005f; if (gamepad.IsLeftThumbStickDown() || gamepad.IsLeftThumbStickLeft()) { @@ -296,7 +302,7 @@ void Sample::Render() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); ID3D12DescriptorHeap* heaps[] = { m_resourceDescriptorHeap->Heap() }; - commandList->SetDescriptorHeaps(_countof(heaps), heaps); + commandList->SetDescriptorHeaps(static_cast(std::size(heaps)), heaps); if (m_bRender2084Curve) { @@ -488,10 +494,10 @@ void Sample::Render2084Curve() m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(viewportWidth, 0.5f, 0), White), VertexPositionColor(Vector3(viewportWidth, viewportHeight, 0), White)); // Render horizontal tick marks - float numSteps = 16; - for (int i = 0; i < numSteps; i++) + constexpr int c_numSteps = 16; + for (int i = 0; i < c_numSteps; i++) { - float x = (i * (viewportWidth / numSteps)) + 0.5f; + float x = (i * (viewportWidth / float(c_numSteps))) + 0.5f; float y = viewportHeight; m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(x, y, 0), White), VertexPositionColor(Vector3(x, y - 10, 0), White)); } @@ -590,7 +596,7 @@ void Sample::Render2084Curve() m_fontBatch->End(); // Render blocks - const long size = 150; + constexpr long size = 150; RECT position = {}; position.left = 1920 - size * 4; position.top = 50; @@ -701,7 +707,7 @@ void Sample::Clear() m_hdrScene->TransitionTo(commandList, D3D12_RESOURCE_STATE_RENDER_TARGET); // Clear the views. - auto rtvDescriptor = m_rtvDescriptorHeap->GetCpuHandle(static_cast(ResourceDescriptors::HDRScene)); + auto const rtvDescriptor = m_rtvDescriptorHeap->GetCpuHandle(static_cast(ResourceDescriptors::HDRScene)); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, nullptr); @@ -710,8 +716,8 @@ void Sample::Clear() commandList->ClearRenderTargetView(rtvDescriptor, Black, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -781,7 +787,7 @@ void Sample::CreateDeviceDependentResources() m_resourceDescriptorHeap->GetCpuHandle(static_cast(ResourceDescriptors::HDRScene)), m_rtvDescriptorHeap->GetCpuHandle(static_cast(RTVDescriptors::HDRScene))); - auto size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); m_hdrScene->SetWindow(size); // Init fonts diff --git a/Samples/Graphics/HDR10/Main.cpp b/Samples/Graphics/HDR10/Main.cpp index bd79f01..d30f2b8 100644 --- a/Samples/Graphics/HDR10/Main.cpp +++ b/Samples/Graphics/HDR10/Main.cpp @@ -29,7 +29,6 @@ namespace std::unique_ptr g_sample; HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; - } LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); @@ -112,7 +111,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -172,7 +171,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); sample->OnResuming(); } diff --git a/Samples/Graphics/HDR10/Readme.docx b/Samples/Graphics/HDR10/Readme.docx index e36ce2a..21217c0 100644 Binary files a/Samples/Graphics/HDR10/Readme.docx and b/Samples/Graphics/HDR10/Readme.docx differ diff --git a/Samples/Graphics/HDR10/StepTimer.h b/Samples/Graphics/HDR10/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/HDR10/StepTimer.h +++ b/Samples/Graphics/HDR10/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/HDR10/pch.h b/Samples/Graphics/HDR10/pch.h index 1b96692..0ff0ef3 100644 --- a/Samples/Graphics/HDR10/pch.h +++ b/Samples/Graphics/HDR10/pch.h @@ -37,8 +37,8 @@ #include -#if _GXDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GXDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -69,6 +69,7 @@ #include #include #include +#include #include diff --git a/Samples/Graphics/HistogramCS/DeviceResources.cpp b/Samples/Graphics/HistogramCS/DeviceResources.cpp index e7d3590..fa67816 100644 --- a/Samples/Graphics/HistogramCS/DeviceResources.cpp +++ b/Samples/Graphics/HistogramCS/DeviceResources.cpp @@ -31,7 +31,7 @@ DeviceResources::DeviceResources( m_rtvDescriptorSize(0), m_screenViewport{}, m_scissorRect{}, - m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_backBufferFormat(backBufferFormat), m_depthBufferFormat(depthBufferFormat), m_backBufferCount(backBufferCount), m_window(nullptr), @@ -54,7 +54,7 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } } @@ -82,6 +82,14 @@ void DeviceResources::CreateDeviceResources() params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); #ifdef _GAMING_XBOX_SCARLETT params.CreateDeviceFlags = createDeviceFlags; + +#if (_GXDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif #endif HRESULT hr = D3D12XboxCreateDevice( @@ -178,6 +186,9 @@ void DeviceResources::CreateDeviceResources() } break; + case XSystemDeviceType::XboxScarlettAnaconda /* Xbox Series X */: + case XSystemDeviceType::XboxOneXDevkit: + case XSystemDeviceType::XboxScarlettDevkit: default: m_outputSize = (m_options & c_Enable4K_UHD) ? RECT{ 0, 0, 3840, 2160 } : RECT{ 0, 0, 2560, 1440 }; break; @@ -225,7 +236,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -264,7 +275,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -277,7 +288,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -290,7 +301,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -326,10 +337,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -337,7 +344,8 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState); m_commandList->ResourceBarrier(1, &barrier); } @@ -349,7 +357,9 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); m_commandList->ResourceBarrier(1, &barrier); } @@ -372,9 +382,10 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const m_commandQueue->PresentX(1, &planeParameters, params) ); - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -396,13 +407,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -411,25 +422,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/Graphics/HistogramCS/DeviceResources.h b/Samples/Graphics/HistogramCS/DeviceResources.h index 012841d..10484d2 100644 --- a/Samples/Graphics/HistogramCS/DeviceResources.h +++ b/Samples/Graphics/HistogramCS/DeviceResources.h @@ -12,9 +12,11 @@ namespace DX class DeviceResources { public: - static constexpr unsigned int c_Enable4K_UHD = 0x1; - static constexpr unsigned int c_EnableQHD = 0x2; - static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_ReverseDepth = 0x8; + static constexpr unsigned int c_AmplificationShaders = 0x10; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -42,6 +44,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -77,7 +80,6 @@ namespace DX } private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; diff --git a/Samples/Graphics/HistogramCS/HistogramCS.cpp b/Samples/Graphics/HistogramCS/HistogramCS.cpp index f7a6ac5..2d762b6 100644 --- a/Samples/Graphics/HistogramCS/HistogramCS.cpp +++ b/Samples/Graphics/HistogramCS/HistogramCS.cpp @@ -70,7 +70,10 @@ Sample::Sample() noexcept(false) : m_technique(HistTGSM) { // Use gamma-correct rendering. - m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, + m_deviceResources = std::make_unique( + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, + DXGI_FORMAT_D32_FLOAT, + 2, DX::DeviceResources::c_Enable4K_UHD | DX::DeviceResources::c_EnableQHD); } @@ -102,6 +105,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); @@ -154,7 +159,7 @@ void Sample::Update(DX::StepTimer const&) } // Limit to avoid looking directly up or down - const float limit = XM_PI / 2.0f - 0.01f; + constexpr float limit = XM_PI / 2.0f - 0.01f; m_pitch = std::max(-limit, std::min(+limit, m_pitch)); if (m_yaw > XM_PI) @@ -198,7 +203,7 @@ void Sample::Render() // Compute histogram { - auto backBuffer = m_deviceResources->GetRenderTarget(); + auto const backBuffer = m_deviceResources->GetRenderTarget(); ScopedBarrier scopeBarrier(commandList, { @@ -212,9 +217,9 @@ void Sample::Render() m_gpuTimer.Start(commandList); - auto vp = m_deviceResources->GetScreenViewport(); + auto const vp = m_deviceResources->GetScreenViewport(); - uint32_t height = static_cast(vp.Height); + auto height = static_cast(vp.Height); CSConstantBuffer cb = { static_cast(vp.Width), height, 0, 0 }; auto cbHandle = m_graphicsMemory->AllocateConstant(cb); @@ -234,7 +239,7 @@ void Sample::Render() } // Visualize the histogram - auto vp = m_deviceResources->GetScreenViewport(); + auto const vp = m_deviceResources->GetScreenViewport(); { D3D12_VIEWPORT vizvp = @@ -281,7 +286,7 @@ void Sample::RenderScene(ID3D12GraphicsCommandList* commandList) m_modelResources->Heap(), m_states->Heap() }; - commandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps); + commandList->SetDescriptorHeaps(static_cast(std::size(descriptorHeaps)), descriptorHeaps); Model::UpdateEffectMatrices(m_modelEffects, SimpleMath::Matrix::Identity, m_view, m_proj); @@ -300,8 +305,8 @@ void Sample::RenderUI(ID3D12GraphicsCommandList* commandList) }; commandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps); - auto size = m_deviceResources->GetOutputSize(); - auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(UINT(size.right), UINT(size.bottom)); + auto const size = m_deviceResources->GetOutputSize(); + auto const safe = SimpleMath::Viewport::ComputeTitleSafeArea(UINT(size.right), UINT(size.bottom)); m_batch->Begin(commandList); @@ -342,8 +347,8 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); // Use linear clear color for gamma-correct rendering. @@ -351,8 +356,8 @@ void Sample::Clear() commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -419,7 +424,7 @@ void Sample::CreateDeviceDependentResources() m_model->LoadStaticBuffers(device, upload); { - RenderTargetState rtStateUI(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState rtStateUI(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); SpriteBatchPipelineStateDescription pd(rtStateUI, &CommonStates::AlphaBlend); m_batch = std::make_unique(device, upload, pd); } @@ -428,7 +433,7 @@ void Sample::CreateDeviceDependentResources() m_deviceResources->WaitForGpu(); finish.wait(); - RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); // Create scene effects. { @@ -564,7 +569,7 @@ void Sample::CreateWindowSizeDependentResources() { m_batch->SetViewport(m_deviceResources->GetScreenViewport()); - auto size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); auto device = m_deviceResources->GetD3DDevice(); diff --git a/Samples/Graphics/HistogramCS/Main.cpp b/Samples/Graphics/HistogramCS/Main.cpp index ae606f3..18e116b 100644 --- a/Samples/Graphics/HistogramCS/Main.cpp +++ b/Samples/Graphics/HistogramCS/Main.cpp @@ -117,7 +117,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -177,7 +177,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); SetDisplayMode(); diff --git a/Samples/Graphics/HistogramCS/Readme.docx b/Samples/Graphics/HistogramCS/Readme.docx index 6b51575..6378336 100644 Binary files a/Samples/Graphics/HistogramCS/Readme.docx and b/Samples/Graphics/HistogramCS/Readme.docx differ diff --git a/Samples/Graphics/HistogramCS/StepTimer.h b/Samples/Graphics/HistogramCS/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/HistogramCS/StepTimer.h +++ b/Samples/Graphics/HistogramCS/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/HistogramCS/pch.h b/Samples/Graphics/HistogramCS/pch.h index 43d021d..e8a282c 100644 --- a/Samples/Graphics/HistogramCS/pch.h +++ b/Samples/Graphics/HistogramCS/pch.h @@ -37,8 +37,8 @@ #include -#if _GXDK_VER < 0x4A610F3C /* GDK Edition 200800 */ -#error This sample requires the August 2020 GDK or later +#if _GXDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -69,6 +69,7 @@ #include #include #include +#include #include diff --git a/Samples/Graphics/HlslCompile/DeviceResources.cpp b/Samples/Graphics/HlslCompile/DeviceResources.cpp index d76fd63..fa67816 100644 --- a/Samples/Graphics/HlslCompile/DeviceResources.cpp +++ b/Samples/Graphics/HlslCompile/DeviceResources.cpp @@ -31,14 +31,13 @@ DeviceResources::DeviceResources( m_rtvDescriptorSize(0), m_screenViewport{}, m_scissorRect{}, - m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_backBufferFormat(backBufferFormat), m_depthBufferFormat(depthBufferFormat), m_backBufferCount(backBufferCount), m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), m_outputSize{0, 0, 1920, 1080}, - m_options(flags), - m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) + m_options(flags) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) { @@ -55,12 +54,16 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } } // Configures the Direct3D device, and stores handles to it and the device context. +#ifdef _GAMING_XBOX_SCARLETT +void DeviceResources::CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags) +#else void DeviceResources::CreateDeviceResources() +#endif { // Create the DX12 API device object. D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; @@ -77,6 +80,17 @@ void DeviceResources::CreateDeviceResources() params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#ifdef _GAMING_XBOX_SCARLETT + params.CreateDeviceFlags = createDeviceFlags; + +#if (_GXDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif +#endif HRESULT hr = D3D12XboxCreateDevice( nullptr, @@ -107,7 +121,7 @@ void DeviceResources::CreateDeviceResources() // Create descriptor heaps for render target views and depth stencil views. D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; - rtvDescriptorHeapDesc.NumDescriptors = (m_options & c_EnableHDR) ? (m_backBufferCount * 2) : m_backBufferCount; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); @@ -152,31 +166,46 @@ void DeviceResources::CreateDeviceResources() m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { - throw std::exception("CreateEvent"); + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } - if (m_options & c_Enable4K_UHD) + if (m_options & (c_Enable4K_UHD | c_EnableQHD)) { switch (XSystemGetDeviceType()) { case XSystemDeviceType::XboxOne: case XSystemDeviceType::XboxOneS: - case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: - m_options &= ~c_Enable4K_UHD; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080)\n"); -#endif + m_options &= ~(c_Enable4K_UHD | c_EnableQHD); break; + case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: + m_options &= ~c_Enable4K_UHD; + if (m_options & c_EnableQHD) + { + m_outputSize = { 0, 0, 2560, 1440 }; + } + break; + + case XSystemDeviceType::XboxScarlettAnaconda /* Xbox Series X */: + case XSystemDeviceType::XboxOneXDevkit: + case XSystemDeviceType::XboxScarlettDevkit: default: - m_outputSize = { 0, 0, 3840, 2160 }; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160)\n"); -#endif + m_outputSize = (m_options & c_Enable4K_UHD) ? RECT{ 0, 0, 3840, 2160 } : RECT{ 0, 0, 2560, 1440 }; break; } } +#ifdef _DEBUG + const char* info = nullptr; + switch (m_outputSize.bottom) + { + case 2160: info = "INFO: Swapchain using 4k (3840 x 2160)\n"; break; + case 1440: info = "INFO: Swapchain using 1440p (2560 x 1440)\n"; break; + default: info = "INFO: Swapchain using 1080p (1920 x 1080)\n"; break; + } + OutputDebugStringA(info); +#endif + RegisterFrameEvents(); } @@ -185,7 +214,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { if (!m_window) { - throw std::exception("Call SetWindow with a valid window handle"); + throw std::logic_error("Call SetWindow with a valid Win32 window handle"); } // Wait until all previous GPU work is complete. @@ -198,7 +227,6 @@ void DeviceResources::CreateWindowSizeDependentResources() for (UINT n = 0; n < m_backBufferCount; n++) { m_renderTargets[n].Reset(); - m_renderTargetsGameDVR[n].Reset(); m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; } @@ -208,7 +236,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -219,6 +247,13 @@ void DeviceResources::CreateWindowSizeDependentResources() ); swapChainBufferDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; +#ifdef _GAMING_XBOX_XBOXONE + if (m_options & c_EnableHDR) + { + swapChainBufferDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_AUTOMATIC_GAMEDVR_TONE_MAP; + } +#endif + D3D12_CLEAR_VALUE swapChainOptimizedClearValue = {}; swapChainOptimizedClearValue.Format = m_backBufferFormat; @@ -240,41 +275,12 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); } - if (m_options & c_EnableHDR) - { - swapChainBufferDesc.Format = swapChainOptimizedClearValue.Format = m_gameDVRFormat; - - for (UINT n = 0; n < m_backBufferCount; n++) - { - ThrowIfFailed(m_d3dDevice->CreateCommittedResource( - &swapChainHeapProperties, - D3D12_HEAP_FLAG_ALLOW_DISPLAY, - &swapChainBufferDesc, - D3D12_RESOURCE_STATE_PRESENT, - &swapChainOptimizedClearValue, - IID_GRAPHICS_PPV_ARGS(m_renderTargetsGameDVR[n].GetAddressOf()))); - - wchar_t name[25] = {}; - swprintf_s(name, L"GameDVR Render target %u", n); - m_renderTargetsGameDVR[n]->SetName(name); - - D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; - rtvDesc.Format = m_gameDVRFormat; - rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + n), m_rtvDescriptorSize); - m_d3dDevice->CreateRenderTargetView(m_renderTargetsGameDVR[n].Get(), &rtvDesc, rtvDescriptorGameDVR); - } - } - // Reset the index to the current back buffer. m_backBufferIndex = 0; @@ -282,7 +288,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -295,7 +301,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -331,10 +337,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -342,23 +344,10 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), - beforeState, afterState), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, afterState); + m_commandList->ResourceBarrier(1, &barrier); } } @@ -368,20 +357,10 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); } // Send the command list off to the GPU for processing. @@ -389,32 +368,24 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); // Present the backbuffer using the PresentX API. - D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters[2] = {}; - planeParameters[0].Token = planeParameters[1].Token = m_framePipelineToken; - planeParameters[0].ResourceCount = planeParameters[1].ResourceCount = 1; - planeParameters[0].ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); + D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters = {}; + planeParameters.Token = m_framePipelineToken; + planeParameters.ResourceCount = 1; + planeParameters.ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); if (m_options & c_EnableHDR) { - planeParameters[0].pSrcViewRects = planeParameters[1].pSrcViewRects = &m_outputSize; - planeParameters[0].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; - planeParameters[1].ppResources = m_renderTargetsGameDVR[m_backBufferIndex].GetAddressOf(); - planeParameters[1].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; - - ThrowIfFailed( - m_commandQueue->PresentX(2, planeParameters, params) - ); - } - else - { - ThrowIfFailed( - m_commandQueue->PresentX(1, planeParameters, params) - ); + planeParameters.ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; } - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + ThrowIfFailed( + m_commandQueue->PresentX(1, &planeParameters, params) + ); - MoveToNextFrame(); + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -436,13 +407,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -451,25 +422,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/Graphics/HlslCompile/DeviceResources.h b/Samples/Graphics/HlslCompile/DeviceResources.h index 1d26b17..4924894 100644 --- a/Samples/Graphics/HlslCompile/DeviceResources.h +++ b/Samples/Graphics/HlslCompile/DeviceResources.h @@ -10,8 +10,11 @@ namespace DX class DeviceResources { public: - static constexpr unsigned int c_Enable4K_UHD = 0x1; - static constexpr unsigned int c_EnableHDR = 0x2; + static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_ReverseDepth = 0x8; + static constexpr unsigned int c_AmplificationShaders = 0x10; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -25,7 +28,11 @@ namespace DX DeviceResources(DeviceResources const&) = delete; DeviceResources& operator= (DeviceResources const&) = delete; +#ifdef _GAMING_XBOX_SCARLETT + void CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags = D3D12XBOX_CREATE_DEVICE_FLAG_NONE); +#else void CreateDeviceResources(); +#endif void CreateWindowSizeDependentResources(); void SetWindow(HWND window) noexcept { m_window = window; } void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT, @@ -35,6 +42,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -67,19 +75,7 @@ namespace DX return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); } - // Direct3D HDR Game DVR support for Xbox One. - ID3D12Resource* GetGameDVRRenderTarget() const noexcept { return m_renderTargetsGameDVR[m_backBufferIndex].Get(); } - DXGI_FORMAT GetGameDVRFormat() const noexcept { return m_gameDVRFormat; } - - CD3DX12_CPU_DESCRIPTOR_HANDLE GetGameDVRRenderTargetView() const noexcept - { - return CD3DX12_CPU_DESCRIPTOR_HANDLE( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + m_backBufferIndex), m_rtvDescriptorSize); - } - private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; @@ -126,9 +122,5 @@ namespace DX // DeviceResources options (see flags above) unsigned int m_options; - - // Direct3D HDR Game DVR support for Xbox One. - Microsoft::WRL::ComPtr m_renderTargetsGameDVR[MAX_BACK_BUFFER_COUNT]; - DXGI_FORMAT m_gameDVRFormat; }; } diff --git a/Samples/Graphics/HlslCompile/HlslCompile.cpp b/Samples/Graphics/HlslCompile/HlslCompile.cpp index 36b6120..4a5e846 100644 --- a/Samples/Graphics/HlslCompile/HlslCompile.cpp +++ b/Samples/Graphics/HlslCompile/HlslCompile.cpp @@ -30,7 +30,9 @@ Sample::Sample() noexcept(false) : m_frame(0) { // Use gamma-correct rendering. - m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, + m_deviceResources = std::make_unique( + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, + 2, DX::DeviceResources::c_Enable4K_UHD); } @@ -41,7 +43,7 @@ void Sample::Initialize(HWND window) m_deviceResources->SetWindow(window); - m_deviceResources->CreateDeviceResources(); + m_deviceResources->CreateDeviceResources(); CreateDeviceDependentResources(); m_deviceResources->CreateWindowSizeDependentResources(); @@ -54,6 +56,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); @@ -85,137 +89,137 @@ void Sample::Update(DX::StepTimer const&) // Draws the scene. void Sample::Render() { - // Don't try to render anything before the first Update. - if (m_timer.GetFrameCount() == 0) - { - return; - } + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } - // Prepare the command list to render a new frame. - m_deviceResources->Prepare(); - Clear(); + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(); + Clear(); - auto commandList = m_deviceResources->GetCommandList(); - PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); - auto size = m_deviceResources->GetOutputSize(); - RECT safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(UINT(size.right), UINT(size.bottom)); + auto const size = m_deviceResources->GetOutputSize(); + auto const safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(UINT(size.right), UINT(size.bottom)); - XMFLOAT2 positionTitle = { (float)safeRect.left, (float)safeRect.top, }; - m_spriteBatch->Begin(commandList); - m_spriteBatch->SetViewport(m_deviceResources->GetScreenViewport()); - m_fontDescription->DrawString(m_spriteBatch.get(), L"HlslCompile sample - To test HLSL symbols, take a PIX GPU capture and examine the pixel shaders for each triangle below", positionTitle); - m_spriteBatch->End(); + XMFLOAT2 positionTitle = { (float)safeRect.left, (float)safeRect.top, }; + m_spriteBatch->Begin(commandList); + m_spriteBatch->SetViewport(m_deviceResources->GetScreenViewport()); + m_fontDescription->DrawString(m_spriteBatch.get(), L"HlslCompile sample - To test HLSL symbols, take a PIX GPU capture and examine the pixel shaders for each triangle below", positionTitle); + m_spriteBatch->End(); - auto width = size.right - size.left; - auto height = size.bottom - size.top; - auto yMargin = 0.02f * height; + auto width = size.right - size.left; + auto height = size.bottom - size.top; + auto yMargin = 0.02f * height; - D3D12_VIEWPORT viewportExample; - viewportExample.TopLeftX = positionTitle.x; - viewportExample.TopLeftY = positionTitle.y + 4.0f * yMargin; - viewportExample.Width = - viewportExample.Height = 0.05f * height; - viewportExample.MinDepth = 0.0f; - viewportExample.MaxDepth = 1.0; + D3D12_VIEWPORT viewportExample; + viewportExample.TopLeftX = positionTitle.x; + viewportExample.TopLeftY = positionTitle.y + 4.0f * yMargin; + viewportExample.Width = + viewportExample.Height = 0.05f * height; + viewportExample.MinDepth = 0.0f; + viewportExample.MaxDepth = 1.0; - auto DrawExample = [commandList, this, &viewportExample](const wchar_t* name, - ID3D12PipelineState* pso)-> void - { - static const VertexPositionColor c_vertexData[3] = - { - { - XMFLOAT3(0.0f, 1.0f, 1.0f), - SimpleMath::Vector4(Colors::Red), - }, // Top / Red - { - XMFLOAT3(1.0f, -1.0f, 1.0f), - SimpleMath::Vector4(Colors::Green), - }, // Right / Green - { - XMFLOAT3(-1.0f, -1.0f, 1.0f), - SimpleMath::Vector4(Colors::Blue), - } // Left / Blue - }; + auto DrawExample = [commandList, this, &viewportExample](const wchar_t* name, + ID3D12PipelineState* pso)-> void + { + static const VertexPositionColor c_vertexData[3] = + { + { + XMFLOAT3(0.0f, 1.0f, 1.0f), + SimpleMath::Vector4(Colors::Red), + }, // Top / Red + { + XMFLOAT3(1.0f, -1.0f, 1.0f), + SimpleMath::Vector4(Colors::Green), + }, // Right / Green + { + XMFLOAT3(-1.0f, -1.0f, 1.0f), + SimpleMath::Vector4(Colors::Blue), + } // Left / Blue + }; - PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, name); - commandList->SetGraphicsRootSignature(m_rootSignature.Get()); - commandList->SetPipelineState(pso); - commandList->RSSetViewports(1, &viewportExample); - m_primitiveBatch->Begin(commandList); - m_primitiveBatch->DrawTriangle(c_vertexData[0], c_vertexData[1], c_vertexData[2]); - m_primitiveBatch->End(); - auto vp = m_deviceResources->GetScreenViewport(); - commandList->RSSetViewports(1, &vp); - PIXEndEvent(commandList); - }; + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, name); + commandList->SetGraphicsRootSignature(m_rootSignature.Get()); + commandList->SetPipelineState(pso); + commandList->RSSetViewports(1, &viewportExample); + m_primitiveBatch->Begin(commandList); + m_primitiveBatch->DrawTriangle(c_vertexData[0], c_vertexData[1], c_vertexData[2]); + m_primitiveBatch->End(); + auto vp = m_deviceResources->GetScreenViewport(); + commandList->RSSetViewports(1, &vp); + PIXEndEvent(commandList); + }; - auto DrawDescription = [this, commandList, &viewportExample, width, yMargin](const wchar_t* description, size_t size)->void - { - auto xTab1 = 0.005f * width; - XMFLOAT2 positionSize = { - viewportExample.TopLeftX + viewportExample.Width + xTab1, - viewportExample.TopLeftY + viewportExample.Height / 2.0f - yMargin / 2.0f, - }; - auto xTab2 = 0.080f * width; - XMFLOAT2 positionDescription = { - positionSize.x + xTab2, - positionSize.y, - }; + auto DrawDescription = [this, commandList, &viewportExample, width, yMargin](const wchar_t* description, size_t size)->void + { + auto xTab1 = 0.005f * width; + XMFLOAT2 positionSize = { + viewportExample.TopLeftX + viewportExample.Width + xTab1, + viewportExample.TopLeftY + viewportExample.Height / 2.0f - yMargin / 2.0f, + }; + auto xTab2 = 0.080f * width; + XMFLOAT2 positionDescription = { + positionSize.x + xTab2, + positionSize.y, + }; - wchar_t buffer[2048] = L""; - swprintf_s(buffer, L"(%6zd bytes)", size); + wchar_t buffer[2048] = L""; + swprintf_s(buffer, L"(%6zd bytes)", size); - m_spriteBatch->Begin(commandList); - m_spriteBatch->SetViewport(m_deviceResources->GetScreenViewport()); - m_fontDescription->DrawString(m_spriteBatch.get(), buffer, positionSize, Colors::Cyan); - m_fontDescription->DrawString(m_spriteBatch.get(), description, positionDescription); - m_spriteBatch->End(); - }; + m_spriteBatch->Begin(commandList); + m_spriteBatch->SetViewport(m_deviceResources->GetScreenViewport()); + m_fontDescription->DrawString(m_spriteBatch.get(), buffer, positionSize, Colors::Cyan); + m_fontDescription->DrawString(m_spriteBatch.get(), description, positionDescription); + m_spriteBatch->End(); + }; - // Draw triangle with each variant of the pixel shader. - // See comments at the CreateGraphicsPipelineState calls later in this file - DrawExample(L"DxcEmbeddedPdb", m_pipelineStateDxcEmbeddedPdb.Get()); - DrawDescription(L"Dxc.exe - Symbols are embedded in the shader binary and automatically found by PIX.", m_sizeDxcEmbeddedPdb); - viewportExample.TopLeftY += viewportExample.Height + yMargin; - DrawExample(L"DxcManualPdb", m_pipelineStateDxcManualPdb.Get()); - DrawDescription(L"Dxc.exe - Symbols are saved to a user-specified pdb file and automatically found by PIX.", m_sizeDxcManualPdb); - viewportExample.TopLeftY += viewportExample.Height + yMargin; - DrawExample(L"DxcAutoPdb", m_pipelineStateDxcAutoPdb.Get()); - DrawDescription(L"Dxc.exe - Symbols are saved to a pdb file with an auto-generated filename, and the user must set a pdb path in PIX.", m_sizeDxcAutoPdb); - viewportExample.TopLeftY += viewportExample.Height + yMargin; + // Draw triangle with each variant of the pixel shader. + // See comments at the CreateGraphicsPipelineState calls later in this file + DrawExample(L"DxcEmbeddedPdb", m_pipelineStateDxcEmbeddedPdb.Get()); + DrawDescription(L"Dxc.exe - Symbols are embedded in the shader binary and automatically found by PIX.", m_sizeDxcEmbeddedPdb); + viewportExample.TopLeftY += viewportExample.Height + yMargin; + DrawExample(L"DxcManualPdb", m_pipelineStateDxcManualPdb.Get()); + DrawDescription(L"Dxc.exe - Symbols are saved to a user-specified pdb file and automatically found by PIX.", m_sizeDxcManualPdb); + viewportExample.TopLeftY += viewportExample.Height + yMargin; + DrawExample(L"DxcAutoPdb", m_pipelineStateDxcAutoPdb.Get()); + DrawDescription(L"Dxc.exe - Symbols are saved to a pdb file with an auto-generated filename, and the user must set a pdb path in PIX.", m_sizeDxcAutoPdb); + viewportExample.TopLeftY += viewportExample.Height + yMargin; - DrawExample(L"DxCompilerEmbeddedPdb", m_pipelineStateDxCompilerEmbeddedPdb.Get()); + DrawExample(L"DxCompilerEmbeddedPdb", m_pipelineStateDxCompilerEmbeddedPdb.Get()); #if _GAMING_XBOX_SCARLETT DrawDescription(L"DxCompiler_xs.dll - Symbols are embedded in the shader binary and automatically found by PIX.", m_sizeDxCompilerEmbeddedPdb); #else DrawDescription(L"DxCompiler_x.dll - Symbols are embedded in the shader binary and automatically found by PIX.", m_sizeDxCompilerEmbeddedPdb); #endif viewportExample.TopLeftY += viewportExample.Height + yMargin; - DrawExample(L"DxCompilerManualPdb", m_pipelineStateDxCompilerManualPdb.Get()); + DrawExample(L"DxCompilerManualPdb", m_pipelineStateDxCompilerManualPdb.Get()); #if _GAMING_XBOX_SCARLETT DrawDescription(L"DxCompiler_xs.dll - Symbols are saved to a user-specified pdb file and automatically found by PIX.", m_sizeDxCompilerManualPdb); #else DrawDescription(L"DxCompiler_x.dll - Symbols are saved to a user-specified pdb file and automatically found by PIX.", m_sizeDxCompilerManualPdb); #endif - viewportExample.TopLeftY += viewportExample.Height + yMargin; - DrawExample(L"DxCompilerAutoPdb", m_pipelineStateDxCompilerAutoPdb.Get()); + viewportExample.TopLeftY += viewportExample.Height + yMargin; + DrawExample(L"DxCompilerAutoPdb", m_pipelineStateDxCompilerAutoPdb.Get()); #if _GAMING_XBOX_SCARLETT DrawDescription(L"DxCompiler_xs.dll - Symbols are saved to a pdb file with an auto-generated filename, and the user must set a pdb path in PIX.", m_sizeDxCompilerAutoPdb); #else DrawDescription(L"DxCompiler_x.dll - Symbols are saved to a pdb file with an auto-generated filename, and the user must set a pdb path in PIX.", m_sizeDxCompilerAutoPdb); #endif - viewportExample.TopLeftY += viewportExample.Height + yMargin; + viewportExample.TopLeftY += viewportExample.Height + yMargin; - PIXEndEvent(commandList); + PIXEndEvent(commandList); - // Show the new frame. - PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); - m_deviceResources->Present(); - PIXBeginEvent(m_deviceResources->GetCommandQueue(), PIX_COLOR_DEFAULT, L"CommitGraphicsMemory"); - m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); - PIXEndEvent(m_deviceResources->GetCommandQueue()); - PIXEndEvent(); + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + PIXBeginEvent(m_deviceResources->GetCommandQueue(), PIX_COLOR_DEFAULT, L"CommitGraphicsMemory"); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); + PIXEndEvent(m_deviceResources->GetCommandQueue()); + PIXEndEvent(); } // Helper method to clear the back buffers. @@ -225,8 +229,8 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); @@ -236,8 +240,8 @@ void Sample::Clear() commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -263,96 +267,96 @@ void Sample::OnResuming() // These are the resources that depend on the device. void Sample::CreateDeviceDependentResources() { - auto device = m_deviceResources->GetD3DDevice(); + auto device = m_deviceResources->GetD3DDevice(); - auto size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); - m_graphicsMemory = std::make_unique(device); + m_graphicsMemory = std::make_unique(device); - // Create root signature. - auto vertexShaderBlob = DX::ReadData(L"VertexShader.cso"); + // Create root signature. + auto vertexShaderBlob = DX::ReadData(L"VertexShader.cso"); - // Xbox One best practice is to use HLSL-based root signatures to support shader precompilation. + // Xbox One best practice is to use HLSL-based root signatures to support shader precompilation. - DX::ThrowIfFailed( - device->CreateRootSignature(0, vertexShaderBlob.data(), vertexShaderBlob.size(), - IID_GRAPHICS_PPV_ARGS(m_rootSignature.ReleaseAndGetAddressOf()))); + DX::ThrowIfFailed( + device->CreateRootSignature(0, vertexShaderBlob.data(), vertexShaderBlob.size(), + IID_GRAPHICS_PPV_ARGS(m_rootSignature.ReleaseAndGetAddressOf()))); - // Create the pipeline state, which includes loading shaders. - // Describe and create the graphics pipeline state object (PSO). - D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; - psoDesc.InputLayout = VertexPositionColor::InputLayout; - psoDesc.pRootSignature = m_rootSignature.Get(); - psoDesc.VS = { vertexShaderBlob.data(), vertexShaderBlob.size() }; - psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); - psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); - psoDesc.DepthStencilState.DepthEnable = FALSE; - psoDesc.DepthStencilState.StencilEnable = FALSE; - psoDesc.DSVFormat = m_deviceResources->GetDepthBufferFormat(); - psoDesc.SampleMask = UINT_MAX; - psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - psoDesc.NumRenderTargets = 1; - psoDesc.RTVFormats[0] = m_deviceResources->GetBackBufferFormat(); - psoDesc.SampleDesc.Count = 1; + // Create the pipeline state, which includes loading shaders. + // Describe and create the graphics pipeline state object (PSO). + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout = VertexPositionColor::InputLayout; + psoDesc.pRootSignature = m_rootSignature.Get(); + psoDesc.VS = { vertexShaderBlob.data(), vertexShaderBlob.size() }; + psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState.DepthEnable = FALSE; + psoDesc.DepthStencilState.StencilEnable = FALSE; + psoDesc.DSVFormat = m_deviceResources->GetDepthBufferFormat(); + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = m_deviceResources->GetBackBufferFormat(); + psoDesc.SampleDesc.Count = 1; - auto LoadPixelShader = [device](const wchar_t *name, D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc, const IID& riid, void** pso) -> size_t - { - auto pixelShaderBlob = DX::ReadData(name); - psoDesc.PS = { pixelShaderBlob.data(), pixelShaderBlob.size() }; + auto LoadPixelShader = [device](const wchar_t *name, D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc, const IID& riid, void** pso) -> size_t + { + auto pixelShaderBlob = DX::ReadData(name); + psoDesc.PS = { pixelShaderBlob.data(), pixelShaderBlob.size() }; DX::ThrowIfFailed(device->CreateGraphicsPipelineState(&psoDesc, riid, pso)); - return pixelShaderBlob.size(); - }; + return pixelShaderBlob.size(); + }; - // The standard pixel shader, compiled with dxc /Zi. - m_sizeDxcEmbeddedPdb = LoadPixelShader(L"PixelShader_Dxc_EmbeddedPdb.cso", psoDesc, IID_GRAPHICS_PPV_ARGS(m_pipelineStateDxcEmbeddedPdb.ReleaseAndGetAddressOf())); + // The standard pixel shader, compiled with dxc /Zi. + m_sizeDxcEmbeddedPdb = LoadPixelShader(L"PixelShader_Dxc_EmbeddedPdb.cso", psoDesc, IID_GRAPHICS_PPV_ARGS(m_pipelineStateDxcEmbeddedPdb.ReleaseAndGetAddressOf())); - // The standard pixel shader, compiled with dxc /Zi /Qstrip_debug /Fd . - m_sizeDxcManualPdb = LoadPixelShader(L"PixelShader_Dxc_ManualPdb.cso", psoDesc, IID_GRAPHICS_PPV_ARGS(m_pipelineStateDxcManualPdb.ReleaseAndGetAddressOf())); + // The standard pixel shader, compiled with dxc /Zi /Qstrip_debug /Fd . + m_sizeDxcManualPdb = LoadPixelShader(L"PixelShader_Dxc_ManualPdb.cso", psoDesc, IID_GRAPHICS_PPV_ARGS(m_pipelineStateDxcManualPdb.ReleaseAndGetAddressOf())); - // The standard pixel shader, compiled with dxc /Zi /Qstrip_debug /Fd \. - // The trailing backslash tells the compiler to automatically choose a filename equal to the shader hash - m_sizeDxcAutoPdb = LoadPixelShader(L"PixelShader_Dxc_AutoPdb.cso", psoDesc, IID_GRAPHICS_PPV_ARGS(m_pipelineStateDxcAutoPdb.ReleaseAndGetAddressOf())); + // The standard pixel shader, compiled with dxc /Zi /Qstrip_debug /Fd \. + // The trailing backslash tells the compiler to automatically choose a filename equal to the shader hash + m_sizeDxcAutoPdb = LoadPixelShader(L"PixelShader_Dxc_AutoPdb.cso", psoDesc, IID_GRAPHICS_PPV_ARGS(m_pipelineStateDxcAutoPdb.ReleaseAndGetAddressOf())); - // The pixel shader compiled with IDxcCompiler and /Zi. - m_sizeDxCompilerEmbeddedPdb = LoadPixelShader(L"PixelShader_DxCompiler_EmbeddedPdb.cso", psoDesc, IID_GRAPHICS_PPV_ARGS(m_pipelineStateDxCompilerEmbeddedPdb.ReleaseAndGetAddressOf())); + // The pixel shader compiled with IDxcCompiler and /Zi. + m_sizeDxCompilerEmbeddedPdb = LoadPixelShader(L"PixelShader_DxCompiler_EmbeddedPdb.cso", psoDesc, IID_GRAPHICS_PPV_ARGS(m_pipelineStateDxCompilerEmbeddedPdb.ReleaseAndGetAddressOf())); - // The pixel shader compiled with IDxcCompiler and /Zi /Qstrip_debug, with the symbols - // saved to a file with a name chosen manually. - m_sizeDxCompilerManualPdb = LoadPixelShader(L"PixelShader_DxCompiler_ManualPdb.cso", psoDesc, IID_GRAPHICS_PPV_ARGS(m_pipelineStateDxCompilerManualPdb.ReleaseAndGetAddressOf())); + // The pixel shader compiled with IDxcCompiler and /Zi /Qstrip_debug, with the symbols + // saved to a file with a name chosen manually. + m_sizeDxCompilerManualPdb = LoadPixelShader(L"PixelShader_DxCompiler_ManualPdb.cso", psoDesc, IID_GRAPHICS_PPV_ARGS(m_pipelineStateDxCompilerManualPdb.ReleaseAndGetAddressOf())); - // The pixel shader compiled with IDxcCompiler and /Zi /Qstrip_debug, with the symbols - // saved to a file named after the shader hash. - m_sizeDxCompilerAutoPdb = LoadPixelShader(L"PixelShader_DxCompiler_AutoPdb.cso", psoDesc, IID_GRAPHICS_PPV_ARGS(m_pipelineStateDxCompilerAutoPdb.ReleaseAndGetAddressOf())); + // The pixel shader compiled with IDxcCompiler and /Zi /Qstrip_debug, with the symbols + // saved to a file named after the shader hash. + m_sizeDxCompilerAutoPdb = LoadPixelShader(L"PixelShader_DxCompiler_AutoPdb.cso", psoDesc, IID_GRAPHICS_PPV_ARGS(m_pipelineStateDxCompilerAutoPdb.ReleaseAndGetAddressOf())); - { - m_primitiveBatch = std::make_unique>(device); + { + m_primitiveBatch = std::make_unique>(device); - m_resourceDescriptorHeap = std::make_unique(device, ResourceDescriptors::Count); + m_resourceDescriptorHeap = std::make_unique(device, ResourceDescriptors::Count); - ResourceUploadBatch resourceUpload(device); - resourceUpload.Begin(); + ResourceUploadBatch resourceUpload(device); + resourceUpload.Begin(); - RenderTargetState renderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); - SpriteBatchPipelineStateDescription pipelineDescription(renderTargetState); - m_spriteBatch = std::make_unique(device, resourceUpload, pipelineDescription); + const RenderTargetState renderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + SpriteBatchPipelineStateDescription pipelineDescription(renderTargetState); + m_spriteBatch = std::make_unique(device, resourceUpload, pipelineDescription); - bool uhd = (size.right - size.left) > 3000; + const bool uhd = (size.right - size.left) > 3000; - m_fontDescription = std::make_unique(device, - resourceUpload, - uhd ? L"SegoeUI_36.spritefont" : L"SegoeUI_18.spritefont", - m_resourceDescriptorHeap->GetCpuHandle(ResourceDescriptors::FontDescription), - m_resourceDescriptorHeap->GetGpuHandle(ResourceDescriptors::FontDescription)); + m_fontDescription = std::make_unique(device, + resourceUpload, + uhd ? L"SegoeUI_36.spritefont" : L"SegoeUI_18.spritefont", + m_resourceDescriptorHeap->GetCpuHandle(ResourceDescriptors::FontDescription), + m_resourceDescriptorHeap->GetGpuHandle(ResourceDescriptors::FontDescription)); - auto uploadResourcesFinished = resourceUpload.End(m_deviceResources->GetCommandQueue()); - uploadResourcesFinished.wait(); // Wait for resources to upload - } + auto uploadResourcesFinished = resourceUpload.End(m_deviceResources->GetCommandQueue()); + uploadResourcesFinished.wait(); // Wait for resources to upload + } - // Wait until assets have been uploaded to the GPU. - m_deviceResources->WaitForGpu(); + // Wait until assets have been uploaded to the GPU. + m_deviceResources->WaitForGpu(); } // Allocate all memory resources that change on a window SizeChanged event. diff --git a/Samples/Graphics/HlslCompile/HlslCompile.h b/Samples/Graphics/HlslCompile/HlslCompile.h index d859638..7d19ca5 100644 --- a/Samples/Graphics/HlslCompile/HlslCompile.h +++ b/Samples/Graphics/HlslCompile/HlslCompile.h @@ -18,6 +18,13 @@ class Sample public: Sample() noexcept(false); + ~Sample() = default; + + Sample(Sample&&) = default; + Sample& operator= (Sample&&) = default; + + Sample(Sample const&) = delete; + Sample& operator= (Sample const&) = delete; // Initialization and management void Initialize(HWND window); @@ -28,9 +35,11 @@ public: // Messages void OnSuspending(); void OnResuming(); + void OnConstrained() {} + void OnUnConstrained() {} - // Properties - bool RequestHDRMode() const { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } + // Properties + bool RequestHDRMode() const noexcept { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } private: @@ -54,46 +63,46 @@ private: // DirectXTK objects. std::unique_ptr m_graphicsMemory; - std::unique_ptr m_resourceDescriptorHeap; + std::unique_ptr m_resourceDescriptorHeap; // Direct3D 12 objects Microsoft::WRL::ComPtr m_rootSignature; Microsoft::WRL::ComPtr m_vertexBuffer; - // Pipeline states for each version of the pixel shader. - // These differ only in compiler arguments pertaining to symbols. + // Pipeline states for each version of the pixel shader. + // These differ only in compiler arguments pertaining to symbols. - Microsoft::WRL::ComPtr m_pipelineStateDxcEmbeddedPdb; - Microsoft::WRL::ComPtr m_pipelineStateDxcManualPdb; - Microsoft::WRL::ComPtr m_pipelineStateDxcAutoPdb; + Microsoft::WRL::ComPtr m_pipelineStateDxcEmbeddedPdb; + Microsoft::WRL::ComPtr m_pipelineStateDxcManualPdb; + Microsoft::WRL::ComPtr m_pipelineStateDxcAutoPdb; - Microsoft::WRL::ComPtr m_pipelineStateDxCompilerEmbeddedPdb; - Microsoft::WRL::ComPtr m_pipelineStateDxCompilerManualPdb; - Microsoft::WRL::ComPtr m_pipelineStateDxCompilerAutoPdb; + Microsoft::WRL::ComPtr m_pipelineStateDxCompilerEmbeddedPdb; + Microsoft::WRL::ComPtr m_pipelineStateDxCompilerManualPdb; + Microsoft::WRL::ComPtr m_pipelineStateDxCompilerAutoPdb; - // Binary sizes - size_t m_sizeDxcEmbeddedPdb; - size_t m_sizeDxcManualPdb; - size_t m_sizeDxcAutoPdb; + // Binary sizes + size_t m_sizeDxcEmbeddedPdb; + size_t m_sizeDxcManualPdb; + size_t m_sizeDxcAutoPdb; - size_t m_sizeDxCompilerEmbeddedPdb; - size_t m_sizeDxCompilerManualPdb; - size_t m_sizeDxCompilerAutoPdb; + size_t m_sizeDxCompilerEmbeddedPdb; + size_t m_sizeDxCompilerManualPdb; + size_t m_sizeDxCompilerAutoPdb; - // Draw helper - std::unique_ptr> - m_primitiveBatch; + // Draw helper + std::unique_ptr> + m_primitiveBatch; - // Fonts - struct ResourceDescriptors - { - enum : uint32_t - { - FontDescription, - Count - }; - }; + // Fonts + struct ResourceDescriptors + { + enum : uint32_t + { + FontDescription, + Count + }; + }; - std::unique_ptr m_spriteBatch; - std::unique_ptr m_fontDescription; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_fontDescription; }; diff --git a/Samples/Graphics/HlslCompile/Main.cpp b/Samples/Graphics/HlslCompile/Main.cpp index 527a0f0..ac29dcd 100644 --- a/Samples/Graphics/HlslCompile/Main.cpp +++ b/Samples/Graphics/HlslCompile/Main.cpp @@ -1,7 +1,7 @@ //-------------------------------------------------------------------------------------- // Main.cpp // -// Entry point for Microsoft GDK with Xbox extensions. +// Entry point for Microsoft GDK with Xbox extensions // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. @@ -18,18 +18,27 @@ using namespace DirectX; +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +#pragma warning(disable : 4061) + namespace { std::unique_ptr g_sample; HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; -}; +} bool g_HDRMode = false; LPCWSTR g_szAppName = L"HLSLSymbols"; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void SetDisplayMode() noexcept; +void ExitSample() noexcept; // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) @@ -57,6 +66,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp // Register class and create window PAPPSTATE_REGISTRATION hPLM = {}; + PAPPCONSTRAIN_REGISTRATION hPLM2 = {}; + { // Register class WNDCLASSEX wcex = {}; @@ -66,7 +77,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp wcex.hInstance = hInstance; wcex.lpszClassName = L"HLSLSymbolsWindowClass"; wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); if (!RegisterClassEx(&wcex)) return 1; @@ -79,17 +90,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp ShowWindow(hwnd, nCmdShow); - if (g_sample->RequestHDRMode()) - { - // Request HDR mode. - auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); - - g_HDRMode = (result == XDisplayHdrModeResult::Enabled); - - #ifdef _DEBUG - OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); - #endif - } + SetDisplayMode(); SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(g_sample.get())); @@ -116,7 +117,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -124,6 +125,13 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp } }, hwnd, &hPLM)) return 1; + + if (RegisterAppConstrainedChangeNotification([](BOOLEAN constrained, PVOID context) + { + // To ensure we use the main UI thread to process the notification, we self-post a message + SendMessage(reinterpret_cast(context), WM_USER + 1, (constrained) ? 1u : 0u, 0); + }, hwnd, &hPLM2)) + return 1; } // Main message loop @@ -144,13 +152,14 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp g_sample.reset(); UnregisterAppStateChangeNotification(hPLM); - + UnregisterAppConstrainedChangeNotification(hPLM2); + CloseHandle(g_plmSuspendComplete); CloseHandle(g_plmSignalResume); XGameRuntimeUninitialize(); - return (int) msg.wParam; + return static_cast(msg.wParam); } // Windows procedure @@ -168,18 +177,52 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); + + SetDisplayMode(); sample->OnResuming(); } break; + + case WM_USER + 1: + if (sample) + { + if (wParam) + { + sample->OnConstrained(); + } + else + { + SetDisplayMode(); + + sample->OnUnConstrained(); + } + } + break; } return DefWindowProc(hWnd, message, wParam, lParam); } +// HDR helper +void SetDisplayMode() noexcept +{ + if (g_sample && g_sample->RequestHDRMode()) + { + // Request HDR mode. + auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); + + g_HDRMode = (result == XDisplayHdrModeResult::Enabled); + +#ifdef _DEBUG + OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); +#endif + } +} + // Exit helper -void ExitSample() +void ExitSample() noexcept { PostQuitMessage(0); } diff --git a/Samples/Graphics/HlslCompile/ReadMe.docx b/Samples/Graphics/HlslCompile/ReadMe.docx index 2428306..2f051f2 100644 Binary files a/Samples/Graphics/HlslCompile/ReadMe.docx and b/Samples/Graphics/HlslCompile/ReadMe.docx differ diff --git a/Samples/Graphics/HlslCompile/StepTimer.h b/Samples/Graphics/HlslCompile/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/HlslCompile/StepTimer.h +++ b/Samples/Graphics/HlslCompile/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/HlslCompile/pch.h b/Samples/Graphics/HlslCompile/pch.h index 771b4d6..5be6a7b 100644 --- a/Samples/Graphics/HlslCompile/pch.h +++ b/Samples/Graphics/HlslCompile/pch.h @@ -37,8 +37,8 @@ #include -#if _GXDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GXDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -56,13 +56,21 @@ #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include +#include +#include +#include -#include #include #include @@ -86,7 +94,7 @@ namespace DX class com_exception : public std::exception { public: - com_exception(HRESULT hr) : result(hr) {} + com_exception(HRESULT hr) noexcept : result(hr) {} const char* what() const override { diff --git a/Samples/Graphics/MeshletCull/DeviceResources.cpp b/Samples/Graphics/MeshletCull/DeviceResources.cpp index dd465d2..2b40774 100644 --- a/Samples/Graphics/MeshletCull/DeviceResources.cpp +++ b/Samples/Graphics/MeshletCull/DeviceResources.cpp @@ -12,7 +12,6 @@ using namespace DX; using Microsoft::WRL::ComPtr; -#ifdef _GAMING_DESKTOP #ifdef __clang__ #pragma clang diagnostic ignored "-Wcovered-switch-default" #pragma clang diagnostic ignored "-Wswitch-enum" @@ -20,6 +19,7 @@ using Microsoft::WRL::ComPtr; #pragma warning(disable : 4061) +#ifdef _GAMING_DESKTOP namespace { inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) noexcept @@ -39,7 +39,8 @@ namespace DeviceResources::DeviceResources( DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, - UINT backBufferCount) noexcept(false) : + UINT backBufferCount, + unsigned int flags) noexcept(false) : m_backBufferIndex(0), m_fenceValues{}, #ifdef _GAMING_XBOX @@ -54,6 +55,7 @@ DeviceResources::DeviceResources( m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_0), m_outputSize{ 0, 0, 1, 1 }, + m_options(flags), m_deviceNotify(nullptr) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) @@ -72,7 +74,7 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } #endif } @@ -98,6 +100,14 @@ void DeviceResources::CreateDeviceResources() params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#if defined(_GAMING_XBOX_SCARLETT) && (_GRDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif + HRESULT hr = D3D12XboxCreateDevice( nullptr, ¶ms, @@ -150,7 +160,7 @@ void DeviceResources::CreateDeviceResources() 80 /* IDXGISwapChain::GetContainingOutput: The swapchain's adapter does not control the output on which the swapchain's window resides. */, }; DXGI_INFO_QUEUE_FILTER filter = {}; - filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.NumIDs = static_cast(std::size(hide)); filter.DenyList.pIDList = hide; dxgiInfoQueue->AddStorageFilterEntries(DXGI_DEBUG_DXGI, &filter); } @@ -198,7 +208,7 @@ void DeviceResources::CreateDeviceResources() static_cast(1323) /* D3D12_MESSAGE_ID_CREATEMESHSHADER_TOPOLOGY_MISMATCH */, }; D3D12_INFO_QUEUE_FILTER filter = {}; - filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.NumIDs = static_cast(std::size(hide)); filter.DenyList.pIDList = hide; d3dInfoQueue->AddStorageFilterEntries(&filter); } @@ -207,6 +217,9 @@ void DeviceResources::CreateDeviceResources() // Determine maximum supported feature level for this device static const D3D_FEATURE_LEVEL s_featureLevels[] = { +#if defined(NTDDI_WIN10_FE) && (NTDDI_VERSION >= NTDDI_WIN10_FE) + D3D_FEATURE_LEVEL_12_2, +#endif D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, D3D_FEATURE_LEVEL_11_1, @@ -215,7 +228,7 @@ void DeviceResources::CreateDeviceResources() D3D12_FEATURE_DATA_FEATURE_LEVELS featLevels = { - _countof(s_featureLevels), s_featureLevels, D3D_FEATURE_LEVEL_11_0 + static_cast(std::size(s_featureLevels)), s_featureLevels, D3D_FEATURE_LEVEL_11_0 }; hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &featLevels, sizeof(featLevels)); @@ -286,7 +299,7 @@ void DeviceResources::CreateDeviceResources() m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { - throw std::exception("CreateEvent"); + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } #ifdef _GAMING_XBOX @@ -299,7 +312,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { if (!m_window) { - throw std::exception("Call SetWindow with a valid window handle"); + throw std::logic_error("Call SetWindow with a valid Win32 window handle"); } // Wait until all previous GPU work is complete. @@ -325,7 +338,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -357,7 +370,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -368,7 +381,7 @@ void DeviceResources::CreateWindowSizeDependentResources() #else // _GAMING_DESKTOP - DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + const DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); // If the swap chain already exists, resize it, otherwise create one. if (m_swapChain) @@ -451,7 +464,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -466,7 +479,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -479,7 +492,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -590,12 +603,6 @@ void DeviceResources::HandleDeviceLost() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { -#ifdef _GAMING_XBOX - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); -#endif - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -603,7 +610,8 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState); m_commandList->ResourceBarrier(1, &barrier); } @@ -615,7 +623,9 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); m_commandList->ResourceBarrier(1, &barrier); } @@ -635,9 +645,12 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) m_commandQueue->PresentX(1, &planeParameters, nullptr) ); - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. -#else + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + +#else // _GAMING_DESKTOP // The first argument instructs DXGI to block until VSync, putting the application // to sleep until the next VSync. This ensures we don't waste any cycles rendering @@ -660,9 +673,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) ThrowIfFailed(hr); } -#endif - MoveToNextFrame(); +#endif } // Handle GPU suspend/resume @@ -688,13 +700,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -703,32 +715,20 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() -{ - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. #ifdef _GAMING_XBOX - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; -#else - m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); -#endif - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() +{ + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } -#ifdef _GAMING_XBOX // Set frame interval and register for frame events void DeviceResources::RegisterFrameEvents() { @@ -757,7 +757,30 @@ void DeviceResources::RegisterFrameEvents() nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE)); } -#else + +#else // _GAMING_DESKTOP + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + // This method acquires the first available hardware adapter that supports Direct3D 12. // If no such adapter can be found, try WARP. Otherwise throw an exception. void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) @@ -799,7 +822,7 @@ void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) // Try WARP12 instead if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) { - throw std::exception("WARP12 not available. Enable the 'Graphics Tools' optional feature"); + throw std::runtime_error("WARP12 not available. Enable the 'Graphics Tools' optional feature"); } OutputDebugStringA("Direct3D Adapter - WARP12\n"); @@ -808,7 +831,7 @@ void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) if (!adapter) { - throw std::exception("No Direct3D 12 device found"); + throw std::runtime_error("No Direct3D 12 device found"); } *ppAdapter = adapter.Detach(); diff --git a/Samples/Graphics/MeshletCull/DeviceResources.h b/Samples/Graphics/MeshletCull/DeviceResources.h index a920f13..0e0aeb0 100644 --- a/Samples/Graphics/MeshletCull/DeviceResources.h +++ b/Samples/Graphics/MeshletCull/DeviceResources.h @@ -22,9 +22,13 @@ namespace DX class DeviceResources { public: + static constexpr unsigned int c_ReverseDepth = 0x1; + static constexpr unsigned int c_AmplificationShaders = 0x2; + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, - UINT backBufferCount = 2) noexcept(false); + UINT backBufferCount = 2, + unsigned int flags = 0) noexcept(false); ~DeviceResources(); DeviceResources(DeviceResources&&) = default; @@ -45,6 +49,9 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; +#ifdef _GAMING_XBOX + void WaitForOrigin(); +#endif // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -68,6 +75,7 @@ namespace DX D3D12_RECT GetScissorRect() const noexcept { return m_scissorRect; } UINT GetCurrentFrameIndex() const noexcept { return m_backBufferIndex; } UINT GetBackBufferCount() const noexcept { return m_backBufferCount; } + unsigned int GetDeviceOptions() const noexcept { return m_options; } CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const noexcept { @@ -81,10 +89,10 @@ namespace DX } private: - void MoveToNextFrame(); #ifdef _GAMING_XBOX void RegisterFrameEvents(); #else + void MoveToNextFrame(); void GetAdapter(IDXGIAdapter1** ppAdapter); #endif @@ -131,6 +139,9 @@ namespace DX D3D_FEATURE_LEVEL m_d3dFeatureLevel; RECT m_outputSize; + // DeviceResources options (see flags above) + unsigned int m_options; + // The IDeviceNotify can be held directly as it owns the DeviceResources. IDeviceNotify* m_deviceNotify; }; diff --git a/Samples/Graphics/MeshletCull/Main.cpp b/Samples/Graphics/MeshletCull/Main.cpp index 17d0897..93d2a4c 100644 --- a/Samples/Graphics/MeshletCull/Main.cpp +++ b/Samples/Graphics/MeshletCull/Main.cpp @@ -20,6 +20,13 @@ using namespace DirectX; +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +#pragma warning(disable : 4061) + namespace { std::unique_ptr g_sample; @@ -27,11 +34,12 @@ namespace HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; #endif -}; +} LPCWSTR g_szAppName = L"Meshlet Culling"; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void ExitSample() noexcept; // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) @@ -55,9 +63,10 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp if (hr == E_GAMERUNTIME_DLL_NOT_FOUND || hr == E_GAMERUNTIME_VERSION_MISMATCH) { #ifdef _GAMING_DESKTOP - (void)MessageBoxW(nullptr, L"Game Runtime is not installed on this system or needs updating.", g_szAppName, MB_ICONERROR | MB_OK); + std::ignore = MessageBoxW(nullptr, L"Game Runtime is not installed on this system or needs updating.", g_szAppName, MB_ICONERROR | MB_OK); #endif } + return 1; } #ifdef _GAMING_XBOX @@ -79,7 +88,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); wcex.lpszClassName = L"SimpleMeshShaderWindowClass"; if (!RegisterClassExW(&wcex)) return 1; @@ -133,7 +142,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -163,20 +172,20 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp #ifdef _GAMING_XBOX UnregisterAppStateChangeNotification(hPLM); - + CloseHandle(g_plmSuspendComplete); CloseHandle(g_plmSignalResume); #endif XGameRuntimeUninitialize(); - return (int) msg.wParam; + return static_cast(msg.wParam); } // Windows procedure LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { -#ifndef _GAMING_XBOX +#ifdef _GAMING_DESKTOP static bool s_in_sizemove = false; static bool s_in_suspend = false; static bool s_minimized = false; @@ -231,7 +240,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); sample->OnResuming(); } @@ -245,7 +254,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) else { PAINTSTRUCT ps; - (void)BeginPaint(hWnd, &ps); + std::ignore = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); } break; @@ -297,12 +306,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_GETMINMAXINFO: - { - auto info = reinterpret_cast(lParam); - info->ptMinTrackSize.x = 320; - info->ptMinTrackSize.y = 200; - } - break; + if (lParam) + { + auto info = reinterpret_cast(lParam); + info->ptMinTrackSize.x = 320; + info->ptMinTrackSize.y = 200; + } + break; case WM_POWERBROADCAST: switch (wParam) @@ -359,7 +369,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); @@ -387,7 +397,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } // Exit helper -void ExitSample() +void ExitSample() noexcept { PostQuitMessage(0); } diff --git a/Samples/Graphics/MeshletCull/MeshletCull.cpp b/Samples/Graphics/MeshletCull/MeshletCull.cpp index 6cdc9d4..eb6b7b2 100644 --- a/Samples/Graphics/MeshletCull/MeshletCull.cpp +++ b/Samples/Graphics/MeshletCull/MeshletCull.cpp @@ -14,7 +14,7 @@ #include "Shared.h" -extern void ExitSample(); +extern void ExitSample() noexcept; using namespace ATG; using namespace DirectX; @@ -27,15 +27,15 @@ namespace //-------------------------------------- // Definitions - static const wchar_t* s_sampleTitle = L"Meshlet Cull"; + const wchar_t* s_sampleTitle = L"Meshlet Cull"; - static const wchar_t* s_meshletCullAsFilename = L"MeshletCullAS.cso"; - static const wchar_t* s_meshletDrawMsFilename = L"BasicMeshletMS.cso"; - static const wchar_t* s_basicdrawPsFilename = L"BasicMeshletPS.cso"; + const wchar_t* s_meshletCullAsFilename = L"MeshletCullAS.cso"; + const wchar_t* s_meshletDrawMsFilename = L"BasicMeshletMS.cso"; + const wchar_t* s_basicdrawPsFilename = L"BasicMeshletPS.cso"; - static const wchar_t* s_meshFilenames[] = + const wchar_t* s_meshFilenames[] = { -#if _GAMING_DESKTOP +#ifdef _GAMING_DESKTOP L"ATGDragon\\Dragon_LOD0.sdkmesh", L"ATGDragon\\Dragon_LOD1.sdkmesh", L"ATGDragon\\Dragon_LOD2.sdkmesh", @@ -184,9 +184,8 @@ namespace } -Sample::Sample() noexcept(false) - : m_deviceResources(std::make_unique()) - , m_displayWidth(0) +Sample::Sample() noexcept(false) + : m_displayWidth(0) , m_displayHeight(0) , m_frame(0) , m_countsData(nullptr) @@ -198,6 +197,9 @@ Sample::Sample() noexcept(false) , m_highlightedIndex(uint32_t(-1)) , m_selectedIndex(uint32_t(-1)) { + m_deviceResources = std::make_unique( + DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_AmplificationShaders); m_deviceResources->RegisterDeviceNotify(this); } @@ -248,6 +250,10 @@ void Sample::Update(DX::StepTimer const& timer) { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); +#ifdef _GAMING_XBOX + m_deviceResources->WaitForOrigin(); +#endif + // Input-agnostic app controls struct AppControls { @@ -487,16 +493,16 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -713,7 +719,7 @@ void Sample::OnResuming() void Sample::OnWindowMoved() { - auto r = m_deviceResources->GetOutputSize(); + auto const r = m_deviceResources->GetOutputSize(); m_deviceResources->WindowSizeChanged(r.right, r.bottom); } @@ -737,7 +743,7 @@ void Sample::GetDefaultSize(int& width, int& height) const // These are the resources that depend on the device. void Sample::CreateDeviceDependentResources() { - auto device = static_cast(m_deviceResources->GetD3DDevice()); + auto device = m_deviceResources->GetD3DDevice(); // Check for Shader Model 6.5 and Mesh Shader feature support #ifdef _GAMING_DESKTOP @@ -973,7 +979,7 @@ void Sample::CreateDeviceDependentResources() // Allocate all memory resources that change on a window SizeChanged event. void Sample::CreateWindowSizeDependentResources() { - RECT size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); m_displayWidth = static_cast(size.right - size.left); m_displayHeight = static_cast(size.bottom - size.top); @@ -1069,7 +1075,7 @@ void Sample::Pick() auto& mesh = model.Model->meshes[0]->opaqueMeshParts[0]; assert(mesh->vbDecl != nullptr); - uint8_t* vbMem = static_cast(mesh->vertexBuffer.Memory()); + auto vbMem = static_cast(mesh->vertexBuffer.Memory()); uint32_t stride = mesh->vertexStride; uint32_t offset = ComputeSemanticByteOffset(*mesh->vbDecl, "SV_Position"); assert(offset != uint32_t(-1)); diff --git a/Samples/Graphics/MeshletCull/StepTimer.h b/Samples/Graphics/MeshletCull/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/MeshletCull/StepTimer.h +++ b/Samples/Graphics/MeshletCull/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/MeshletCull/pch.h b/Samples/Graphics/MeshletCull/pch.h index a424700..487f495 100644 --- a/Samples/Graphics/MeshletCull/pch.h +++ b/Samples/Graphics/MeshletCull/pch.h @@ -41,8 +41,8 @@ #include -#if _GRDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GRDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -68,14 +68,20 @@ #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include - -#include -#include +#include +#include +#include #ifdef _GAMING_XBOX #include @@ -159,9 +165,9 @@ namespace DX class com_exception : public std::exception { public: - com_exception(HRESULT hr) : result(hr) {} + com_exception(HRESULT hr) noexcept : result(hr) {} - virtual const char* what() const override + const char* what() const override { static char s_str[64] = {}; sprintf_s(s_str, "Failure with HRESULT of %08X", static_cast(result)); @@ -177,6 +183,12 @@ namespace DX { if (FAILED(hr)) { +#ifdef _DEBUG + char str[64] = {}; + sprintf_s(str, "**ERROR** Fatal Error with HRESULT of %08X\n", static_cast(hr)); + OutputDebugStringA(str); + __debugbreak(); +#endif throw com_exception(hr); } } diff --git a/Samples/Graphics/MeshletInstancing/DeviceResources.cpp b/Samples/Graphics/MeshletInstancing/DeviceResources.cpp index 7d88350..2b40774 100644 --- a/Samples/Graphics/MeshletInstancing/DeviceResources.cpp +++ b/Samples/Graphics/MeshletInstancing/DeviceResources.cpp @@ -12,7 +12,6 @@ using namespace DX; using Microsoft::WRL::ComPtr; -#ifdef _GAMING_DESKTOP #ifdef __clang__ #pragma clang diagnostic ignored "-Wcovered-switch-default" #pragma clang diagnostic ignored "-Wswitch-enum" @@ -20,6 +19,7 @@ using Microsoft::WRL::ComPtr; #pragma warning(disable : 4061) +#ifdef _GAMING_DESKTOP namespace { inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) noexcept @@ -39,7 +39,8 @@ namespace DeviceResources::DeviceResources( DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, - UINT backBufferCount) noexcept(false) : + UINT backBufferCount, + unsigned int flags) noexcept(false) : m_backBufferIndex(0), m_fenceValues{}, #ifdef _GAMING_XBOX @@ -54,6 +55,7 @@ DeviceResources::DeviceResources( m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_0), m_outputSize{ 0, 0, 1, 1 }, + m_options(flags), m_deviceNotify(nullptr) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) @@ -72,7 +74,7 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } #endif } @@ -98,6 +100,14 @@ void DeviceResources::CreateDeviceResources() params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#if defined(_GAMING_XBOX_SCARLETT) && (_GRDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif + HRESULT hr = D3D12XboxCreateDevice( nullptr, ¶ms, @@ -150,7 +160,7 @@ void DeviceResources::CreateDeviceResources() 80 /* IDXGISwapChain::GetContainingOutput: The swapchain's adapter does not control the output on which the swapchain's window resides. */, }; DXGI_INFO_QUEUE_FILTER filter = {}; - filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.NumIDs = static_cast(std::size(hide)); filter.DenyList.pIDList = hide; dxgiInfoQueue->AddStorageFilterEntries(DXGI_DEBUG_DXGI, &filter); } @@ -194,9 +204,11 @@ void DeviceResources::CreateDeviceResources() // Workarounds for debug layer issues on hybrid-graphics systems D3D12_MESSAGE_ID_EXECUTECOMMANDLISTS_WRONGSWAPCHAINBUFFERREFERENCE, D3D12_MESSAGE_ID_RESOURCE_BARRIER_MISMATCHING_COMMAND_LIST_TYPE, + // Workaround for debug layer issues with mesh shader validation. + static_cast(1323) /* D3D12_MESSAGE_ID_CREATEMESHSHADER_TOPOLOGY_MISMATCH */, }; D3D12_INFO_QUEUE_FILTER filter = {}; - filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.NumIDs = static_cast(std::size(hide)); filter.DenyList.pIDList = hide; d3dInfoQueue->AddStorageFilterEntries(&filter); } @@ -205,6 +217,9 @@ void DeviceResources::CreateDeviceResources() // Determine maximum supported feature level for this device static const D3D_FEATURE_LEVEL s_featureLevels[] = { +#if defined(NTDDI_WIN10_FE) && (NTDDI_VERSION >= NTDDI_WIN10_FE) + D3D_FEATURE_LEVEL_12_2, +#endif D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, D3D_FEATURE_LEVEL_11_1, @@ -213,7 +228,7 @@ void DeviceResources::CreateDeviceResources() D3D12_FEATURE_DATA_FEATURE_LEVELS featLevels = { - _countof(s_featureLevels), s_featureLevels, D3D_FEATURE_LEVEL_11_0 + static_cast(std::size(s_featureLevels)), s_featureLevels, D3D_FEATURE_LEVEL_11_0 }; hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &featLevels, sizeof(featLevels)); @@ -284,7 +299,7 @@ void DeviceResources::CreateDeviceResources() m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { - throw std::exception("CreateEvent"); + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } #ifdef _GAMING_XBOX @@ -297,7 +312,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { if (!m_window) { - throw std::exception("Call SetWindow with a valid window handle"); + throw std::logic_error("Call SetWindow with a valid Win32 window handle"); } // Wait until all previous GPU work is complete. @@ -323,7 +338,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -355,7 +370,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -366,7 +381,7 @@ void DeviceResources::CreateWindowSizeDependentResources() #else // _GAMING_DESKTOP - DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + const DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); // If the swap chain already exists, resize it, otherwise create one. if (m_swapChain) @@ -449,7 +464,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -464,7 +479,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -477,7 +492,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -588,12 +603,6 @@ void DeviceResources::HandleDeviceLost() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { -#ifdef _GAMING_XBOX - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); -#endif - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -601,7 +610,8 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState); m_commandList->ResourceBarrier(1, &barrier); } @@ -613,7 +623,9 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); m_commandList->ResourceBarrier(1, &barrier); } @@ -633,9 +645,12 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) m_commandQueue->PresentX(1, &planeParameters, nullptr) ); - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. -#else + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + +#else // _GAMING_DESKTOP // The first argument instructs DXGI to block until VSync, putting the application // to sleep until the next VSync. This ensures we don't waste any cycles rendering @@ -658,9 +673,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) ThrowIfFailed(hr); } -#endif - MoveToNextFrame(); +#endif } // Handle GPU suspend/resume @@ -686,13 +700,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -701,32 +715,20 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() -{ - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. #ifdef _GAMING_XBOX - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; -#else - m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); -#endif - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() +{ + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } -#ifdef _GAMING_XBOX // Set frame interval and register for frame events void DeviceResources::RegisterFrameEvents() { @@ -755,7 +757,30 @@ void DeviceResources::RegisterFrameEvents() nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE)); } -#else + +#else // _GAMING_DESKTOP + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + // This method acquires the first available hardware adapter that supports Direct3D 12. // If no such adapter can be found, try WARP. Otherwise throw an exception. void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) @@ -797,7 +822,7 @@ void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) // Try WARP12 instead if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) { - throw std::exception("WARP12 not available. Enable the 'Graphics Tools' optional feature"); + throw std::runtime_error("WARP12 not available. Enable the 'Graphics Tools' optional feature"); } OutputDebugStringA("Direct3D Adapter - WARP12\n"); @@ -806,7 +831,7 @@ void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) if (!adapter) { - throw std::exception("No Direct3D 12 device found"); + throw std::runtime_error("No Direct3D 12 device found"); } *ppAdapter = adapter.Detach(); diff --git a/Samples/Graphics/MeshletInstancing/DeviceResources.h b/Samples/Graphics/MeshletInstancing/DeviceResources.h index a920f13..0e0aeb0 100644 --- a/Samples/Graphics/MeshletInstancing/DeviceResources.h +++ b/Samples/Graphics/MeshletInstancing/DeviceResources.h @@ -22,9 +22,13 @@ namespace DX class DeviceResources { public: + static constexpr unsigned int c_ReverseDepth = 0x1; + static constexpr unsigned int c_AmplificationShaders = 0x2; + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, - UINT backBufferCount = 2) noexcept(false); + UINT backBufferCount = 2, + unsigned int flags = 0) noexcept(false); ~DeviceResources(); DeviceResources(DeviceResources&&) = default; @@ -45,6 +49,9 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; +#ifdef _GAMING_XBOX + void WaitForOrigin(); +#endif // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -68,6 +75,7 @@ namespace DX D3D12_RECT GetScissorRect() const noexcept { return m_scissorRect; } UINT GetCurrentFrameIndex() const noexcept { return m_backBufferIndex; } UINT GetBackBufferCount() const noexcept { return m_backBufferCount; } + unsigned int GetDeviceOptions() const noexcept { return m_options; } CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const noexcept { @@ -81,10 +89,10 @@ namespace DX } private: - void MoveToNextFrame(); #ifdef _GAMING_XBOX void RegisterFrameEvents(); #else + void MoveToNextFrame(); void GetAdapter(IDXGIAdapter1** ppAdapter); #endif @@ -131,6 +139,9 @@ namespace DX D3D_FEATURE_LEVEL m_d3dFeatureLevel; RECT m_outputSize; + // DeviceResources options (see flags above) + unsigned int m_options; + // The IDeviceNotify can be held directly as it owns the DeviceResources. IDeviceNotify* m_deviceNotify; }; diff --git a/Samples/Graphics/MeshletInstancing/Main.cpp b/Samples/Graphics/MeshletInstancing/Main.cpp index 390eddd..89278e8 100644 --- a/Samples/Graphics/MeshletInstancing/Main.cpp +++ b/Samples/Graphics/MeshletInstancing/Main.cpp @@ -20,6 +20,13 @@ using namespace DirectX; +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +#pragma warning(disable : 4061) + namespace { std::unique_ptr g_sample; @@ -27,11 +34,12 @@ namespace HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; #endif -}; +} LPCWSTR g_szAppName = L"Meshlet Instancing"; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void ExitSample() noexcept; // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) @@ -55,7 +63,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp if (hr == E_GAMERUNTIME_DLL_NOT_FOUND || hr == E_GAMERUNTIME_VERSION_MISMATCH) { #ifdef _GAMING_DESKTOP - (void)MessageBoxW(nullptr, L"Game Runtime is not installed on this system or needs updating.", g_szAppName, MB_ICONERROR | MB_OK); + std::ignore = MessageBoxW(nullptr, L"Game Runtime is not installed on this system or needs updating.", g_szAppName, MB_ICONERROR | MB_OK); #endif } return 1; @@ -80,7 +88,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); wcex.lpszClassName = L"MeshletInstancingWindowClass"; if (!RegisterClassExW(&wcex)) return 1; @@ -134,7 +142,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -164,14 +172,14 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp #ifdef _GAMING_XBOX UnregisterAppStateChangeNotification(hPLM); - + CloseHandle(g_plmSuspendComplete); CloseHandle(g_plmSignalResume); #endif XGameRuntimeUninitialize(); - return (int) msg.wParam; + return static_cast(msg.wParam); } // Windows procedure @@ -232,7 +240,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); sample->OnResuming(); } @@ -246,7 +254,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) else { PAINTSTRUCT ps; - (void)BeginPaint(hWnd, &ps); + std::ignore = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); } break; @@ -298,12 +306,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_GETMINMAXINFO: - { - auto info = reinterpret_cast(lParam); - info->ptMinTrackSize.x = 320; - info->ptMinTrackSize.y = 200; - } - break; + if (lParam) + { + auto info = reinterpret_cast(lParam); + info->ptMinTrackSize.x = 320; + info->ptMinTrackSize.y = 200; + } + break; case WM_POWERBROADCAST: switch (wParam) @@ -360,7 +369,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); @@ -388,7 +397,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } // Exit helper -void ExitSample() +void ExitSample() noexcept { PostQuitMessage(0); } diff --git a/Samples/Graphics/MeshletInstancing/MeshletInstancing.cpp b/Samples/Graphics/MeshletInstancing/MeshletInstancing.cpp index 9f70c57..00c012a 100644 --- a/Samples/Graphics/MeshletInstancing/MeshletInstancing.cpp +++ b/Samples/Graphics/MeshletInstancing/MeshletInstancing.cpp @@ -14,7 +14,7 @@ #pragma warning( disable : 4324 4365 ) -extern void ExitSample(); +extern void ExitSample() noexcept; using namespace ATG; using namespace DirectX; @@ -33,9 +33,9 @@ namespace const wchar_t* s_meshShaderFilename = L"InstancedMeshletMS.cso"; const wchar_t* s_pixelShaderFilename = L"BasicMeshletPS.cso"; - static const wchar_t* s_lodFilenames[] = + const wchar_t* s_lodFilenames[] = { -#if _GAMING_DESKTOP +#ifdef _GAMING_DESKTOP L"ATGDragon\\Dragon_LOD0.sdkmesh", L"ATGDragon\\Dragon_LOD1.sdkmesh", L"ATGDragon\\Dragon_LOD2.sdkmesh", @@ -51,7 +51,7 @@ namespace L"Dragon_LOD5.sdkmesh", #endif }; - const uint32_t c_lodCount = _countof(s_lodFilenames); + constexpr uint32_t c_lodCount = _countof(s_lodFilenames); #ifdef _GAMING_XBOX_SCARLETT const uint32_t c_textureDataPitchAlign = D3D12XBOX_TEXTURE_DATA_PITCH_ALIGNMENT; @@ -85,7 +85,7 @@ namespace template size_t GetAlignedSize(T size) { - const size_t alignment = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT; + constexpr size_t alignment = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT; const size_t alignedSize = (size + alignment - 1) & ~(alignment - 1); return alignedSize; } @@ -109,8 +109,7 @@ namespace } Sample::Sample() noexcept(false) - : m_deviceResources(std::make_unique()) - , m_displayWidth(0) + : m_displayWidth(0) , m_displayHeight(0) , m_frame(0) , m_instMode(InstanceMode::IM_Line) @@ -120,6 +119,7 @@ Sample::Sample() noexcept(false) , m_updateInstances(false) , m_renderHelp(false) { + m_deviceResources = std::make_unique(); m_deviceResources->RegisterDeviceNotify(this); } @@ -135,13 +135,15 @@ Sample::~Sample() void Sample::Initialize(HWND window, int width, int height) { m_gamePad = std::make_unique(); + m_keyboard = std::make_unique(); + m_mouse = std::make_unique(); m_mouse->SetWindow(window); m_deviceResources->SetWindow(window, width, height); - m_deviceResources->CreateDeviceResources(); + m_deviceResources->CreateDeviceResources(); CreateDeviceDependentResources(); m_deviceResources->CreateWindowSizeDependentResources(); @@ -154,6 +156,10 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); +#ifdef _GAMING_XBOX + m_deviceResources->WaitForOrigin(); +#endif + m_timer.Tick([&]() { Update(m_timer); @@ -168,7 +174,6 @@ void Sample::Tick() // Updates the world. void Sample::Update(DX::StepTimer const& timer) { - PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); float elapsedTime = float(timer.GetElapsedSeconds()); @@ -348,16 +353,16 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -397,7 +402,7 @@ void Sample::UpdateConstants(ID3D12GraphicsCommandList* commandList) void Sample::DrawHUD(ID3D12GraphicsCommandList* commandList) { - const wchar_t* c_renderModeNames[] = + static const wchar_t* c_renderModeNames[] = { L"Flat", L"Meshlets" @@ -407,7 +412,7 @@ void Sample::DrawHUD(ID3D12GraphicsCommandList* commandList) m_hudBatch->Begin(commandList); - auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(m_displayWidth, m_displayHeight); + auto const safe = SimpleMath::Viewport::ComputeTitleSafeArea(m_displayWidth, m_displayHeight); // Draw a text underlay box m_hudBatch->Draw(m_srvPile->GetGpuHandle(SRV_WhiteTexture), { 1, 1 }, RECT{ safe.left - 10, safe.top - 10, safe.left + 335, safe.top + 270 }); @@ -508,7 +513,7 @@ void Sample::OnResuming() void Sample::OnWindowMoved() { - auto r = m_deviceResources->GetOutputSize(); + auto const r = m_deviceResources->GetOutputSize(); m_deviceResources->WindowSizeChanged(r.right, r.bottom); } @@ -521,7 +526,7 @@ void Sample::OnWindowSizeChanged(int width, int height) } // Properties -void Sample::GetDefaultSize(int& width, int& height) const +void Sample::GetDefaultSize(int& width, int& height) const noexcept { width = 1280; height = 720; @@ -556,11 +561,9 @@ void Sample::CreateDeviceDependentResources() // Instantiate manager objects m_graphicsMemory = std::make_unique(device); m_gpuTimer = std::make_unique(device, m_deviceResources->GetCommandQueue()); - m_controlHelp = std::make_unique(L"Meshlet Instancing", nullptr, c_buttonAssignment, _countof(c_buttonAssignment)); + m_controlHelp = std::make_unique(L"Meshlet Instancing", nullptr, c_buttonAssignment, std::size(c_buttonAssignment)); m_srvPile = std::make_unique(device, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 128, DescriptorHeapIndex::SRV_Count); @@ -599,7 +602,7 @@ void Sample::CreateDeviceDependentResources() // Create GPU resources for various purposes { // Create constant resources - auto defaultHeap = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES defaultHeap(D3D12_HEAP_TYPE_DEFAULT); auto cbDesc = CD3DX12_RESOURCE_DESC::Buffer(GetAlignedSize(sizeof(Constants))); DX::ThrowIfFailed(device->CreateCommittedResource( @@ -626,13 +629,13 @@ void Sample::CreateDeviceDependentResources() } // Load the model LODs and mesh data - m_lods.resize(_countof(s_lodFilenames)); - m_primCounts.resize(_countof(s_lodFilenames)); + m_lods.resize(std::size(s_lodFilenames)); + m_primCounts.resize(std::size(s_lodFilenames)); for (size_t i = 0; i < m_lods.size(); ++i) { - wchar_t filepath[256]; - DX::FindMediaFile(filepath, _countof(filepath), s_lodFilenames[i]); + wchar_t filepath[_MAX_PATH] = {}; + DX::FindMediaFile(filepath, _MAX_PATH, s_lodFilenames[i]); m_lods[i].Model = Model::CreateFromSDKMESH(device, filepath); @@ -675,7 +678,7 @@ void Sample::CreateDeviceDependentResources() } // Create our HUD objects - auto backBufferRts = RenderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState backBufferRts(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); m_controlHelp->RestoreDevice(device, resourceUpload, backBufferRts); auto spritePSD = SpriteBatchPipelineStateDescription(backBufferRts, &CommonStates::AlphaBlend); @@ -715,7 +718,7 @@ void Sample::CreateDeviceDependentResources() // Allocate all memory resources that change on a window SizeChanged event. void Sample::CreateWindowSizeDependentResources() { - RECT size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); m_displayWidth = size.right - size.left; m_displayHeight = size.bottom - size.top; @@ -766,7 +769,7 @@ void Sample::RegenerateInstances() m_updateInstances = true; const float radius = m_lods[m_lodIndex].Model->meshes[0]->boundingSphere.Radius; - const float padding = 0.5f; + constexpr float padding = 0.5f; const float spacing = (1.0f + padding) * radius; // Determine our instancing mode diff --git a/Samples/Graphics/MeshletInstancing/MeshletInstancing.h b/Samples/Graphics/MeshletInstancing/MeshletInstancing.h index 15a0651..0c9c75a 100644 --- a/Samples/Graphics/MeshletInstancing/MeshletInstancing.h +++ b/Samples/Graphics/MeshletInstancing/MeshletInstancing.h @@ -25,6 +25,12 @@ public: Sample() noexcept(false); ~Sample(); + Sample(Sample&&) = default; + Sample& operator= (Sample&&) = default; + + Sample(Sample const&) = delete; + Sample& operator= (Sample const&) = delete; + // Initialization and management void Initialize(HWND window, int width, int height); @@ -44,7 +50,7 @@ public: void OnWindowSizeChanged(int width, int height); // Properties - void GetDefaultSize(int& width, int& height) const; + void GetDefaultSize(int& width, int& height) const noexcept; private: void Update(DX::StepTimer const& timer); diff --git a/Samples/Graphics/MeshletInstancing/ReadMe.docx b/Samples/Graphics/MeshletInstancing/ReadMe.docx index cdb1435..aadf172 100644 Binary files a/Samples/Graphics/MeshletInstancing/ReadMe.docx and b/Samples/Graphics/MeshletInstancing/ReadMe.docx differ diff --git a/Samples/Graphics/MeshletInstancing/StepTimer.h b/Samples/Graphics/MeshletInstancing/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/MeshletInstancing/StepTimer.h +++ b/Samples/Graphics/MeshletInstancing/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/MeshletInstancing/pch.h b/Samples/Graphics/MeshletInstancing/pch.h index ced9b03..7c19e00 100644 --- a/Samples/Graphics/MeshletInstancing/pch.h +++ b/Samples/Graphics/MeshletInstancing/pch.h @@ -41,8 +41,8 @@ #include -#if _GRDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GRDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -68,17 +68,23 @@ #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include #include #include #include - -#include -#include +#include +#include +#include #ifdef _GAMING_XBOX #include @@ -91,28 +97,29 @@ #include #include "CommonStates.h" -#include "ControllerFont.h" -#include "ControllerHelp.h" #include "DescriptorHeap.h" #include "DirectXHelpers.h" -#include "FlyCamera.h" #include "GamePad.h" #include "GraphicsMemory.h" #include "Keyboard.h" -#include "Meshlet.h" #include "Model.h" #include "Mouse.h" +#include "RenderTargetState.h" +#include "ResourceUploadBatch.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" + +#include "ControllerFont.h" +#include "ControllerHelp.h" +#include "FlyCamera.h" +#include "Meshlet.h" #ifdef _GAMING_XBOX_SCARLETT #include "PerformanceTimersXbox.h" #else #include "PerformanceTimers.h" #endif #include "ReadData.h" -#include "RenderTargetState.h" -#include "ResourceUploadBatch.h" -#include "SimpleMath.h" -#include "SpriteBatch.h" -#include "SpriteFont.h" namespace DX { @@ -120,7 +127,7 @@ namespace DX class com_exception : public std::exception { public: - com_exception(HRESULT hr) : result(hr) {} + com_exception(HRESULT hr) noexcept : result(hr) {} const char* what() const override { diff --git a/Samples/Graphics/PointSprites/DeviceResources.cpp b/Samples/Graphics/PointSprites/DeviceResources.cpp index 12f2b99..fa67816 100644 --- a/Samples/Graphics/PointSprites/DeviceResources.cpp +++ b/Samples/Graphics/PointSprites/DeviceResources.cpp @@ -25,19 +25,19 @@ DeviceResources::DeviceResources( DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) noexcept(false) : - m_backBufferIndex(0), - m_fenceValues{}, - m_framePipelineToken{}, - m_rtvDescriptorSize(0), - m_screenViewport{}, - m_scissorRect{}, - m_backBufferFormat(backBufferFormat), - m_depthBufferFormat(depthBufferFormat), - m_backBufferCount(backBufferCount), - m_window(nullptr), - m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), - m_outputSize{ 0, 0, 1920, 1080 }, - m_options(flags) + m_backBufferIndex(0), + m_fenceValues{}, + m_framePipelineToken{}, + m_rtvDescriptorSize(0), + m_screenViewport{}, + m_scissorRect{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) { @@ -54,12 +54,16 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } } // Configures the Direct3D device, and stores handles to it and the device context. +#ifdef _GAMING_XBOX_SCARLETT +void DeviceResources::CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags) +#else void DeviceResources::CreateDeviceResources() +#endif { // Create the DX12 API device object. D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; @@ -76,6 +80,17 @@ void DeviceResources::CreateDeviceResources() params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#ifdef _GAMING_XBOX_SCARLETT + params.CreateDeviceFlags = createDeviceFlags; + +#if (_GXDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif +#endif HRESULT hr = D3D12XboxCreateDevice( nullptr, @@ -151,31 +166,46 @@ void DeviceResources::CreateDeviceResources() m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { - throw std::exception("CreateEvent"); + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } - if (m_options & c_Enable4K_UHD) + if (m_options & (c_Enable4K_UHD | c_EnableQHD)) { switch (XSystemGetDeviceType()) { case XSystemDeviceType::XboxOne: case XSystemDeviceType::XboxOneS: - case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: - m_options &= ~c_Enable4K_UHD; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080)\n"); -#endif + m_options &= ~(c_Enable4K_UHD | c_EnableQHD); break; + case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: + m_options &= ~c_Enable4K_UHD; + if (m_options & c_EnableQHD) + { + m_outputSize = { 0, 0, 2560, 1440 }; + } + break; + + case XSystemDeviceType::XboxScarlettAnaconda /* Xbox Series X */: + case XSystemDeviceType::XboxOneXDevkit: + case XSystemDeviceType::XboxScarlettDevkit: default: - m_outputSize = { 0, 0, 3840, 2160 }; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160)\n"); -#endif + m_outputSize = (m_options & c_Enable4K_UHD) ? RECT{ 0, 0, 3840, 2160 } : RECT{ 0, 0, 2560, 1440 }; break; } } +#ifdef _DEBUG + const char* info = nullptr; + switch (m_outputSize.bottom) + { + case 2160: info = "INFO: Swapchain using 4k (3840 x 2160)\n"; break; + case 1440: info = "INFO: Swapchain using 1440p (2560 x 1440)\n"; break; + default: info = "INFO: Swapchain using 1080p (1920 x 1080)\n"; break; + } + OutputDebugStringA(info); +#endif + RegisterFrameEvents(); } @@ -184,7 +214,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { if (!m_window) { - throw std::exception("Call SetWindow with a valid window handle"); + throw std::logic_error("Call SetWindow with a valid Win32 window handle"); } // Wait until all previous GPU work is complete. @@ -206,7 +236,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -217,6 +247,13 @@ void DeviceResources::CreateWindowSizeDependentResources() ); swapChainBufferDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; +#ifdef _GAMING_XBOX_XBOXONE + if (m_options & c_EnableHDR) + { + swapChainBufferDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_AUTOMATIC_GAMEDVR_TONE_MAP; + } +#endif + D3D12_CLEAR_VALUE swapChainOptimizedClearValue = {}; swapChainOptimizedClearValue.Format = m_backBufferFormat; @@ -238,7 +275,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -251,7 +288,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -259,12 +296,12 @@ void DeviceResources::CreateWindowSizeDependentResources() backBufferHeight, 1, // This depth stencil view has only one texture. 1 // Use a single mipmap level. - ); + ); depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -274,7 +311,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_RESOURCE_STATE_DEPTH_WRITE, &depthOptimizedClearValue, IID_GRAPHICS_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) - )); + )); m_depthStencil->SetName(L"Depth stencil"); @@ -300,10 +337,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -311,7 +344,8 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState); m_commandList->ResourceBarrier(1, &barrier); } @@ -323,7 +357,9 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); m_commandList->ResourceBarrier(1, &barrier); } @@ -337,13 +373,19 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const planeParameters.ResourceCount = 1; planeParameters.ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); + if (m_options & c_EnableHDR) + { + planeParameters.ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; + } + ThrowIfFailed( m_commandQueue->PresentX(1, &planeParameters, params) ); - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -365,13 +407,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -380,25 +422,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/Graphics/PointSprites/DeviceResources.h b/Samples/Graphics/PointSprites/DeviceResources.h index 5088b68..4924894 100644 --- a/Samples/Graphics/PointSprites/DeviceResources.h +++ b/Samples/Graphics/PointSprites/DeviceResources.h @@ -10,12 +10,16 @@ namespace DX class DeviceResources { public: - static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_ReverseDepth = 0x8; + static constexpr unsigned int c_AmplificationShaders = 0x10; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, - UINT backBufferCount = 2, - unsigned int flags = 0) noexcept(false); + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0) noexcept(false); ~DeviceResources(); DeviceResources(DeviceResources&&) = default; @@ -24,36 +28,41 @@ namespace DX DeviceResources(DeviceResources const&) = delete; DeviceResources& operator= (DeviceResources const&) = delete; +#ifdef _GAMING_XBOX_SCARLETT + void CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags = D3D12XBOX_CREATE_DEVICE_FLAG_NONE); +#else void CreateDeviceResources(); +#endif void CreateWindowSizeDependentResources(); void SetWindow(HWND window) noexcept { m_window = window; } void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT, - D3D12_RESOURCE_STATES afterState = D3D12_RESOURCE_STATE_RENDER_TARGET); + D3D12_RESOURCE_STATES afterState = D3D12_RESOURCE_STATE_RENDER_TARGET); void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET, - _In_opt_ const D3D12XBOX_PRESENT_PARAMETERS* params = nullptr); + _In_opt_ const D3D12XBOX_PRESENT_PARAMETERS* params = nullptr); void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } // Direct3D Accessors. - auto GetD3DDevice() const noexcept { return m_d3dDevice.Get(); } - HWND GetWindow() const noexcept { return m_window; } + auto GetD3DDevice() const noexcept { return m_d3dDevice.Get(); } + HWND GetWindow() const noexcept { return m_window; } D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const noexcept { return m_d3dFeatureLevel; } - ID3D12Resource* GetRenderTarget() const noexcept { return m_renderTargets[m_backBufferIndex].Get(); } - ID3D12Resource* GetDepthStencil() const noexcept { return m_depthStencil.Get(); } - ID3D12CommandQueue* GetCommandQueue() const noexcept { return m_commandQueue.Get(); } - ID3D12CommandAllocator* GetCommandAllocator() const noexcept { return m_commandAllocators[m_backBufferIndex].Get(); } - auto GetCommandList() const noexcept { return m_commandList.Get(); } - DXGI_FORMAT GetBackBufferFormat() const noexcept { return m_backBufferFormat; } - DXGI_FORMAT GetDepthBufferFormat() const noexcept { return m_depthBufferFormat; } - D3D12_VIEWPORT GetScreenViewport() const noexcept { return m_screenViewport; } - D3D12_RECT GetScissorRect() const noexcept { return m_scissorRect; } - UINT GetCurrentFrameIndex() const noexcept { return m_backBufferIndex; } - UINT GetBackBufferCount() const noexcept { return m_backBufferCount; } - unsigned int GetDeviceOptions() const noexcept { return m_options; } + ID3D12Resource* GetRenderTarget() const noexcept { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const noexcept { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const noexcept { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const noexcept { return m_commandAllocators[m_backBufferIndex].Get(); } + auto GetCommandList() const noexcept { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const noexcept { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const noexcept { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const noexcept { return m_screenViewport; } + D3D12_RECT GetScissorRect() const noexcept { return m_scissorRect; } + UINT GetCurrentFrameIndex() const noexcept { return m_backBufferIndex; } + UINT GetBackBufferCount() const noexcept { return m_backBufferCount; } + unsigned int GetDeviceOptions() const noexcept { return m_options; } CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const noexcept { @@ -67,7 +76,6 @@ namespace DX } private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; diff --git a/Samples/Graphics/PointSprites/Main.cpp b/Samples/Graphics/PointSprites/Main.cpp index d5f79c4..0f753f1 100644 --- a/Samples/Graphics/PointSprites/Main.cpp +++ b/Samples/Graphics/PointSprites/Main.cpp @@ -13,18 +13,30 @@ #include "ATGTelemetry.h" #include +#include #include using namespace DirectX; +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +#pragma warning(disable : 4061) + namespace { std::unique_ptr g_sample; HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; -}; +} + +bool g_HDRMode = false; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void SetDisplayMode() noexcept; +void ExitSample() noexcept; // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) @@ -55,6 +67,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp // Register class and create window PAPPSTATE_REGISTRATION hPLM = {}; + PAPPCONSTRAIN_REGISTRATION hPLM2 = {}; + { // Register class WNDCLASSEXA wcex = {}; @@ -63,7 +77,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.lpszClassName = u8"PointSpritesWindowClass"; - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); if (!RegisterClassExA(&wcex)) return 1; @@ -76,6 +90,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp ShowWindow(hwnd, nCmdShow); + SetDisplayMode(); + SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(g_sample.get())); // Sample Usage Telemetry @@ -91,23 +107,30 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp return 1; if (RegisterAppStateChangeNotification([](BOOLEAN quiesced, PVOID context) + { + if (quiesced) { - if (quiesced) - { - ResetEvent(g_plmSuspendComplete); - ResetEvent(g_plmSignalResume); + ResetEvent(g_plmSuspendComplete); + ResetEvent(g_plmSignalResume); - // To ensure we use the main UI thread to process the notification, we self-post a message - PostMessage(reinterpret_cast(context), WM_USER, 0, 0); + // To ensure we use the main UI thread to process the notification, we self-post a message + PostMessage(reinterpret_cast(context), WM_USER, 0, 0); - // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); - } - else - { - SetEvent(g_plmSignalResume); - } - }, hwnd, &hPLM)) + // To defer suspend, you must wait to exit this callback + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); + } + else + { + SetEvent(g_plmSignalResume); + } + }, hwnd, &hPLM)) + return 1; + + if (RegisterAppConstrainedChangeNotification([](BOOLEAN constrained, PVOID context) + { + // To ensure we use the main UI thread to process the notification, we self-post a message + SendMessage(reinterpret_cast(context), WM_USER + 1, (constrained) ? 1u : 0u, 0); + }, hwnd, &hPLM2)) return 1; } @@ -129,6 +152,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp g_sample.reset(); UnregisterAppStateChangeNotification(hPLM); + UnregisterAppConstrainedChangeNotification(hPLM2); CloseHandle(g_plmSuspendComplete); CloseHandle(g_plmSignalResume); @@ -153,16 +177,50 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); + + SetDisplayMode(); sample->OnResuming(); } break; + + case WM_USER + 1: + if (sample) + { + if (wParam) + { + sample->OnConstrained(); + } + else + { + SetDisplayMode(); + + sample->OnUnConstrained(); + } + } + break; } return DefWindowProc(hWnd, message, wParam, lParam); } +// HDR helper +void SetDisplayMode() noexcept +{ + if (g_sample && g_sample->RequestHDRMode()) + { + // Request HDR mode. + auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); + + g_HDRMode = (result == XDisplayHdrModeResult::Enabled); + +#ifdef _DEBUG + OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); +#endif + } +} + // Exit helper void ExitSample() noexcept { diff --git a/Samples/Graphics/PointSprites/PointSprites.cpp b/Samples/Graphics/PointSprites/PointSprites.cpp index dea49e8..16994d5 100644 --- a/Samples/Graphics/PointSprites/PointSprites.cpp +++ b/Samples/Graphics/PointSprites/PointSprites.cpp @@ -10,7 +10,7 @@ #include "ATGColors.h" -extern void ExitSample(); +extern void ExitSample() noexcept; using namespace DirectX; @@ -21,23 +21,25 @@ namespace //------------------------------------- // Sample Constants - const wchar_t* g_sampleTitle = L"Point Sprites"; + const wchar_t* g_sampleTitle = L"Point Sprites"; - const int s_vertexStride = (3 + 4) * 4; - const int s_numParticles = 32 * 1024; - const float s_maxParticleColor = 0.2f; - const float s_maxParticleSize = 30.0f; - const float s_defaultParticleSize = 4.0f; - const int s_runsPerTest = 3; - const int s_runsPerSequence = 2; + constexpr int c_vertexStride = (3 + 4) * 4; + constexpr int c_numParticles = 32 * 1024; + constexpr float c_maxParticleColor = 0.2f; + constexpr float c_maxParticleSize = 30.0f; + constexpr float c_defaultParticleSize = 4.0f; + constexpr int c_runsPerTest = 3; + constexpr int c_runsPerSequence = 2; - const D3D12_INPUT_ELEMENT_DESC s_elementDesc[] = + constexpr uint32_t c_elementDescNum = 2; + + const D3D12_INPUT_ELEMENT_DESC s_elementDesc[c_elementDescNum] = { { "TEXCOORD", 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 }, }; - const D3D12_INPUT_ELEMENT_DESC s_instanceElementDesc[] = + const D3D12_INPUT_ELEMENT_DESC s_instanceElementDesc[c_elementDescNum] = { { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 }, @@ -50,7 +52,7 @@ Sample::Sample() noexcept(false) , m_displayHeight(0) , m_frame(0) , m_vbView{} - , m_particleSize(s_defaultParticleSize) + , m_particleSize(c_defaultParticleSize) , m_zeroViewport(false) , m_refreshParticles(true) , m_selectorIdx(0) @@ -90,6 +92,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); @@ -118,7 +122,7 @@ void Sample::Update(DX::StepTimer const&) if (pad.IsAPressed()) { - m_particleSize = std::min(m_particleSize + 0.5f, s_maxParticleSize); + m_particleSize = std::min(m_particleSize + 0.5f, c_maxParticleSize); m_refreshParticles = true; } @@ -189,13 +193,13 @@ void Sample::Render() // Set the common resource state to the pipeline. ID3D12DescriptorHeap* heaps[] = { m_srvPile->Heap() }; - commandList->SetDescriptorHeaps(_countof(heaps), heaps); + commandList->SetDescriptorHeaps(static_cast(std::size(heaps)), heaps); commandList->SetGraphicsRootSignature(m_commonRS.Get()); float cbData[] = { 1.f / m_displayWidth, 1.f / m_displayHeight, }; commandList->SetGraphicsRoot32BitConstants(RS_ConstantBuffer, 2, &cbData, 0); - commandList->SetGraphicsRoot32BitConstant(RS_ConstantBuffer, UINT(s_numParticles), 2); + commandList->SetGraphicsRoot32BitConstant(RS_ConstantBuffer, UINT(c_numParticles), 2); commandList->SetGraphicsRootShaderResourceView(RS_VertexBuffer, m_vertices->GetGPUVirtualAddress()); commandList->SetGraphicsRootDescriptorTable(RS_ParticleTex, m_srvPile->GetGpuHandle(SRV_ParticleTex)); @@ -203,21 +207,21 @@ void Sample::Render() ClearTestResults(); - // Run the forward sequence test s_runsPerSequence times - for (int i = 0; i < s_runsPerSequence; ++i) + // Run the forward sequence test c_runsPerSequence times + for (int i = 0; i < c_runsPerSequence; ++i) { RunTests(m_forwardSequence, commandList); } - // Run the random sequence test s_runsPerSequence times - for (int i = 0; i < s_runsPerSequence; ++i) + // Run the random sequence test c_runsPerSequence times + for (int i = 0; i < c_runsPerSequence; ++i) { CreateRandomTestSequence(m_randomSequence); RunTests(m_randomSequence, commandList); } - // Run the reverse sequence test s_runsPerSequence times - for (int i = 0; i < s_runsPerSequence; ++i) + // Run the reverse sequence test c_runsPerSequence times + for (int i = 0; i < c_runsPerSequence; ++i) { RunTests(m_reverseSequence, commandList); } @@ -239,11 +243,11 @@ void Sample::Render() m_hudBatch->Begin(commandList); - const float ParticleCountPerTest = float(s_numParticles * s_runsPerTest) * 0.000001f; // In millions - const float TotalParticleCount = float(s_numParticles * s_runsPerTest * s_runsPerSequence * 3 * enabledTestCount) * 0.000001f; // In millions + const float ParticleCountPerTest = float(c_numParticles * c_runsPerTest) * 0.000001f; // In millions + const float TotalParticleCount = float(c_numParticles * c_runsPerTest * c_runsPerSequence * 3 * enabledTestCount) * 0.000001f; // In millions wchar_t textBuffer[1024] = {}; - swprintf_s(textBuffer, _countof(textBuffer), + swprintf_s(textBuffer, L"Particles per Test: %.2f mln \n" "Total Rendered Particles: %.2f mln\n" "ParticleSize: %.1f\n" @@ -288,10 +292,10 @@ void Sample::Render() Test& test = *it; auto testColor = test.Enabled ? DirectX::Colors::Green : DirectX::Colors::Red; - swprintf_s(textBuffer, _countof(textBuffer), L"%s", test.Name); + swprintf_s(textBuffer, L"%s", test.Name); m_smallFont->DrawString(m_hudBatch.get(), textBuffer, XMFLOAT2(xPos - 460, yPos), testColor); - swprintf_s(textBuffer, _countof(textBuffer), L"%.2f", test.AverageTimeResult); + swprintf_s(textBuffer, L"%.2f", test.AverageTimeResult); float xOffset = XMVectorGetX(m_smallFont->MeasureString(textBuffer)); m_smallFont->DrawString(m_hudBatch.get(), textBuffer, XMFLOAT2(xPos - xOffset, yPos), testColor); @@ -322,16 +326,16 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); commandList->ClearRenderTargetView(rtvDescriptor, DirectX::Colors::Black, 0, nullptr); commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -364,15 +368,13 @@ void Sample::CreateDeviceDependentResources() m_gpuTimer = std::make_unique(device, m_deviceResources->GetCommandQueue()); m_commonStates = std::make_unique(device); m_srvPile = std::make_unique(device, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 128, SRV_Count); auto resourceUpload = ResourceUploadBatch(device); resourceUpload.Begin(); - auto backBufferRts = RenderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState backBufferRts(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); auto spritePSD = SpriteBatchPipelineStateDescription(backBufferRts, &CommonStates::AlphaBlend); m_hudBatch = std::make_unique(device, resourceUpload, spritePSD); @@ -383,8 +385,8 @@ void Sample::CreateDeviceDependentResources() finished.wait(); // Create our vertex buffer resource. - auto defaultHeapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); - auto desc = CD3DX12_RESOURCE_DESC::Buffer(s_vertexStride * s_numParticles); + const CD3DX12_HEAP_PROPERTIES defaultHeapProps(D3D12_HEAP_TYPE_DEFAULT); + auto desc = CD3DX12_RESOURCE_DESC::Buffer(c_vertexStride * c_numParticles); DX::ThrowIfFailed(device->CreateCommittedResource( &defaultHeapProps, @@ -397,8 +399,8 @@ void Sample::CreateDeviceDependentResources() m_vertices->SetName(L"Vertex Buffer"); m_vbView.BufferLocation = m_vertices->GetGPUVirtualAddress(); - m_vbView.SizeInBytes = s_vertexStride * s_numParticles; - m_vbView.StrideInBytes = s_vertexStride; + m_vbView.SizeInBytes = c_vertexStride * c_numParticles; + m_vbView.StrideInBytes = c_vertexStride; CreateTestPSOs(); } @@ -481,7 +483,7 @@ void Sample::CreateTestPSOs() auto nativeQuadInstVS = DX::ReadData(L"RenderNativeQuadInstancingVS.cso"); psoDesc.InputLayout.pInputElementDescs = s_instanceElementDesc; - psoDesc.InputLayout.NumElements = _countof(s_instanceElementDesc); + psoDesc.InputLayout.NumElements = c_elementDescNum; psoDesc.VS = { nativeQuadInstVS.data(), nativeQuadInstVS.size() }; psoDesc.PrimitiveTopologyType = D3D12XBOX_PRIMITIVE_TOPOLOGY_TYPE_QUAD; @@ -493,7 +495,7 @@ void Sample::CreateTestPSOs() auto triStripQuadInstVS = DX::ReadData(L"RenderTriangleStripQuadInstancingVS.cso"); psoDesc.InputLayout.pInputElementDescs = s_instanceElementDesc; - psoDesc.InputLayout.NumElements = _countof(s_instanceElementDesc); + psoDesc.InputLayout.NumElements = c_elementDescNum; psoDesc.VS = { triStripQuadInstVS.data(), triStripQuadInstVS.size() }; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; @@ -538,7 +540,7 @@ void Sample::CreateTestPSOs() auto render3InstVS = DX::ReadData(L"Render3InstancingVS.cso"); psoDesc.InputLayout.pInputElementDescs = s_instanceElementDesc; - psoDesc.InputLayout.NumElements = _countof(s_instanceElementDesc); + psoDesc.InputLayout.NumElements = c_elementDescNum; psoDesc.VS = { render3InstVS.data(), render3InstVS.size() }; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; @@ -550,7 +552,7 @@ void Sample::CreateTestPSOs() auto render4InstVS = DX::ReadData(L"Render4InstancingVS.cso"); psoDesc.InputLayout.pInputElementDescs = s_instanceElementDesc; - psoDesc.InputLayout.NumElements = _countof(s_instanceElementDesc); + psoDesc.InputLayout.NumElements = c_elementDescNum; psoDesc.VS = { render4InstVS.data(), render4InstVS.size() }; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; @@ -563,7 +565,7 @@ void Sample::CreateTestPSOs() // OffChip psoDesc.InputLayout.pInputElementDescs = s_elementDesc; - psoDesc.InputLayout.NumElements = _countof(s_elementDesc); + psoDesc.InputLayout.NumElements = c_elementDescNum; psoDesc.VS = { passVS.data(), passVS.size() }; psoDesc.GS = { expand3GS.data(), expand3GS.size() }; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; @@ -571,7 +573,7 @@ void Sample::CreateTestPSOs() DX::ThrowIfFailed(device->CreateGraphicsPipelineState(&psoDesc, IID_GRAPHICS_PPV_ARGS(m_triGeoOffChipPSO.ReleaseAndGetAddressOf()))); } -#ifdef _GAMING_XBOX_XBOXONE // Xbox Scarlett doesn't have on/off-chip specification +#ifdef _GAMING_XBOX_XBOXONE // Xbox Series X|S doesn't have on/off-chip specification { auto expand3OnChipGS = DX::ReadData(L"Expand3OnChipGS.cso"); @@ -590,7 +592,7 @@ void Sample::CreateTestPSOs() // OffChip psoDesc.InputLayout.pInputElementDescs = s_elementDesc; - psoDesc.InputLayout.NumElements = _countof(s_elementDesc); + psoDesc.InputLayout.NumElements = c_elementDescNum; psoDesc.VS = { passVS.data(), passVS.size() }; psoDesc.GS = { expand4GS.data(), expand4GS.size() }; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; @@ -599,7 +601,7 @@ void Sample::CreateTestPSOs() DX::ThrowIfFailed(device->CreateGraphicsPipelineState(&psoDesc, IID_GRAPHICS_PPV_ARGS(m_quadGeoOffChipPSO.ReleaseAndGetAddressOf()))); } -#ifdef _GAMING_XBOX_XBOXONE // Xbox Scarlett doesn't have on/off-chip specification +#ifdef _GAMING_XBOX_XBOXONE // Xbox Series X|S doesn't have on/off-chip specification { auto expand4OnChipGS = DX::ReadData(L"Expand4OnChipGS.cso"); @@ -626,7 +628,7 @@ void Sample::CreateTestPSOs() DX::ThrowIfFailed(device->CreateGraphicsPipelineState(&psoDesc, IID_GRAPHICS_PPV_ARGS(m_onlyTriGeoOffChipPSO.ReleaseAndGetAddressOf()))); } -#ifdef _GAMING_XBOX_XBOXONE // Xbox Scarlett doesn't have on/off-chip specification +#ifdef _GAMING_XBOX_XBOXONE // Xbox Series X|S doesn't have on/off-chip specification { auto onlyExpand3OnChipGS = DX::ReadData(L"OnlyExpand3OnChipGS.cso"); @@ -653,7 +655,7 @@ void Sample::CreateTestPSOs() DX::ThrowIfFailed(device->CreateGraphicsPipelineState(&psoDesc, IID_GRAPHICS_PPV_ARGS(m_onlyQuadGeoOffChipPSO.ReleaseAndGetAddressOf()))); } -#ifdef _GAMING_XBOX_XBOXONE // Xbox Scarlett doesn't have on/off-chip specification +#ifdef _GAMING_XBOX_XBOXONE // Xbox Series X|S doesn't have on/off-chip specification { auto onlyExpand4OnChipGS = DX::ReadData(L"OnlyExpand4OnChipGS.cso"); @@ -672,7 +674,7 @@ void Sample::CreateTestPSOs() auto render3DS = DX::ReadData(L"Render3DS.cso"); psoDesc.InputLayout.pInputElementDescs = s_elementDesc; - psoDesc.InputLayout.NumElements = _countof(s_elementDesc); + psoDesc.InputLayout.NumElements = c_elementDescNum; psoDesc.VS = { passVS.data(), passVS.size() }; psoDesc.HS = { render3HS.data(), render3HS.size() }; psoDesc.DS = { render3DS.data(), render3DS.size() }; @@ -689,7 +691,7 @@ void Sample::CreateTestPSOs() auto render4DS = DX::ReadData(L"Render4DS.cso"); psoDesc.InputLayout.pInputElementDescs = s_elementDesc; - psoDesc.InputLayout.NumElements = _countof(s_elementDesc); + psoDesc.InputLayout.NumElements = c_elementDescNum; psoDesc.VS = { passVS.data(), passVS.size() }; psoDesc.HS = { render4HS.data(), render4HS.size() }; psoDesc.DS = { render4DS.data(), render4DS.size() }; @@ -740,8 +742,8 @@ void Sample::UpdateVertexData(ID3D12GraphicsCommandList* commandList) srand(0); // Generate the vertex data - static float vbData[7 * s_numParticles]; - for (int i = 0; i < s_numParticles; ++i) + static float vbData[7 * c_numParticles]; + for (int i = 0; i < c_numParticles; ++i) { float* p = &vbData[i * 7]; @@ -749,9 +751,9 @@ void Sample::UpdateVertexData(ID3D12GraphicsCommandList* commandList) p[1] = m_displayHeight * (float)rand() / (float)RAND_MAX; p[2] = m_particleSize * (float)rand() / (float)RAND_MAX; - p[3] = s_maxParticleColor * (float)rand() / (float)RAND_MAX; - p[4] = s_maxParticleColor * (float)rand() / (float)RAND_MAX; - p[5] = s_maxParticleColor * (float)rand() / (float)RAND_MAX; + p[3] = c_maxParticleColor * (float)rand() / (float)RAND_MAX; + p[4] = c_maxParticleColor * (float)rand() / (float)RAND_MAX; + p[5] = c_maxParticleColor * (float)rand() / (float)RAND_MAX; p[6] = (float)rand() / (float)RAND_MAX; } @@ -785,7 +787,7 @@ void Sample::RegisterTests() RegisterTest(true, L"VS instanced triangles", &Sample::TestVSInstancedTriangles); RegisterTest(true, L"VS instanced quads", &Sample::TestVSInstancedQuads); -#ifdef _GAMING_XBOX_XBOXONE // Xbox Scarlett doesn't have on/off-chip specification +#ifdef _GAMING_XBOX_XBOXONE // Xbox Series X|S doesn't have on/off-chip specification RegisterTest(true, L"GS triangles (off chip - default)", &Sample::TestGSTriangles); RegisterTest(true, L"GS quads (off chip - default)", &Sample::TestGSQuads); RegisterTest(true, L"GS only triangles (off chip - default)", &Sample::TestGSOnlyTriangles); @@ -934,10 +936,10 @@ void Sample::TestVSNativeQuads(Test& test, ID3D12GraphicsCommandList* commandLis commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_QUADLIST); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { // multiplying the number of verts by 4 because each 4 verts will make a quad - commandList->DrawInstanced(s_numParticles * 4, 1, 0, 0); + commandList->DrawInstanced(c_numParticles * 4, 1, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); } @@ -948,9 +950,9 @@ void Sample::TestVSNativeInstancedQuads(Test& test, ID3D12GraphicsCommandList* c commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_QUADLIST); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { - commandList->DrawInstanced(4, s_numParticles, 0, 0); + commandList->DrawInstanced(4, c_numParticles, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); } @@ -961,10 +963,10 @@ void Sample::TestVSTriangleStripInstancedQuads(Test& test, ID3D12GraphicsCommand commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { // multiplying the number of verts by 4 because each 4 verts will make a quad - commandList->DrawInstanced(4, s_numParticles, 0, 0); + commandList->DrawInstanced(4, c_numParticles, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); } @@ -975,10 +977,10 @@ void Sample::TestVSRectListQuads(Test& test, ID3D12GraphicsCommandList* commandL commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_RECTLIST); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { // multiplying the number of verts by 3 because each 3 verts will make a quad - commandList->DrawInstanced(s_numParticles * 3, 1, 0, 0); + commandList->DrawInstanced(c_numParticles * 3, 1, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); } @@ -989,10 +991,10 @@ void Sample::TestVSTriangles(Test& test, ID3D12GraphicsCommandList* commandList) commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { // multiplying the number of verts by 3 because each 3 verts will make a triangle - commandList->DrawInstanced(s_numParticles * 3, 1, 0, 0); + commandList->DrawInstanced(c_numParticles * 3, 1, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); } @@ -1003,10 +1005,10 @@ void Sample::TestVSQuads(Test& test, ID3D12GraphicsCommandList* commandList) commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { // multiplying the number of verts by 6 because each 6 verts will make two triangles - commandList->DrawInstanced(s_numParticles * 6, 1, 0, 0); + commandList->DrawInstanced(c_numParticles * 6, 1, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); } @@ -1017,9 +1019,9 @@ void Sample::TestVSInstancedTriangles(Test& test, ID3D12GraphicsCommandList* com commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { - commandList->DrawInstanced(3, s_numParticles, 0, 0); + commandList->DrawInstanced(3, c_numParticles, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); } @@ -1030,9 +1032,9 @@ void Sample::TestVSInstancedQuads(Test& test, ID3D12GraphicsCommandList* command commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { - commandList->DrawInstanced(6, s_numParticles, 0, 0); + commandList->DrawInstanced(6, c_numParticles, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); } @@ -1048,9 +1050,9 @@ void Sample::TestGSTriangles(Test& test, ID3D12GraphicsCommandList* commandList) commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { - commandList->DrawInstanced(s_numParticles, 1, 0, 0); + commandList->DrawInstanced(c_numParticles, 1, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); } @@ -1062,9 +1064,9 @@ void Sample::TestGSQuads(Test& test, ID3D12GraphicsCommandList* commandList) commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { - commandList->DrawInstanced(s_numParticles, 1, 0, 0); + commandList->DrawInstanced(c_numParticles, 1, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); } @@ -1076,9 +1078,9 @@ void Sample::TestGSOnlyTriangles(Test& test, ID3D12GraphicsCommandList* commandL commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { - commandList->DrawInstanced(s_numParticles, 1, 0, 0); + commandList->DrawInstanced(c_numParticles, 1, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); } @@ -1090,9 +1092,9 @@ void Sample::TestGSOnlyQuads(Test& test, ID3D12GraphicsCommandList* commandList) commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { - commandList->DrawInstanced(s_numParticles, 1, 0, 0); + commandList->DrawInstanced(c_numParticles, 1, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); @@ -1107,9 +1109,9 @@ void Sample::TestDSTriangles(Test& test, ID3D12GraphicsCommandList* commandList) commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { - commandList->DrawInstanced(s_numParticles, 1, 0, 0); + commandList->DrawInstanced(c_numParticles, 1, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); @@ -1121,9 +1123,9 @@ void Sample::TestDSQuads(Test& test, ID3D12GraphicsCommandList* commandList) commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST); m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { - commandList->DrawInstanced(s_numParticles, 1, 0, 0); + commandList->DrawInstanced(c_numParticles, 1, 0, 0); } m_gpuTimer->Stop(commandList, test.Id); @@ -1140,11 +1142,11 @@ void Sample::TestMSTriangles(Test& test, ID3D12GraphicsCommandList* commandList) commandList->SetPipelineState(m_msPSO.Get()); commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - uint32_t totalVertCount = (s_numParticles * 4); + uint32_t totalVertCount = (c_numParticles * 4); uint32_t groupCount = (totalVertCount + 31) / 32; m_gpuTimer->Start(commandList, test.Id); - for (int i = 0; i < s_runsPerTest; ++i) + for (int i = 0; i < c_runsPerTest; ++i) { cmdList->DispatchMesh(groupCount, 1, 1); } diff --git a/Samples/Graphics/PointSprites/PointSprites.h b/Samples/Graphics/PointSprites/PointSprites.h index 68a1876..c7e3a10 100644 --- a/Samples/Graphics/PointSprites/PointSprites.h +++ b/Samples/Graphics/PointSprites/PointSprites.h @@ -35,6 +35,11 @@ public: // Messages void OnSuspending(); void OnResuming(); + void OnConstrained() {} + void OnUnConstrained() {} + + // Properties + bool RequestHDRMode() const noexcept { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } private: diff --git a/Samples/Graphics/PointSprites/StepTimer.h b/Samples/Graphics/PointSprites/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/PointSprites/StepTimer.h +++ b/Samples/Graphics/PointSprites/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/PointSprites/pch.h b/Samples/Graphics/PointSprites/pch.h index aa900ed..7408827 100644 --- a/Samples/Graphics/PointSprites/pch.h +++ b/Samples/Graphics/PointSprites/pch.h @@ -37,8 +37,8 @@ #include -#if _GXDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GXDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -53,19 +53,27 @@ #include #include + #include #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include +#include +#include +#include #include -#include -#include #include #include @@ -73,27 +81,28 @@ #include #include "CommonStates.h" -#include "ControllerFont.h" #include "DDSTextureLoader.h" #include "DescriptorHeap.h" #include "DirectXHelpers.h" #include "GamePad.h" #include "GraphicsMemory.h" -#include "PerformanceTimersXbox.h" -#include "ReadData.h" #include "RenderTargetState.h" #include "ResourceUploadBatch.h" #include "SimpleMath.h" #include "SpriteBatch.h" #include "SpriteFont.h" +#include "ControllerFont.h" +#include "PerformanceTimersXbox.h" +#include "ReadData.h" + namespace DX { // Helper class for COM exceptions class com_exception : public std::exception { public: - com_exception(HRESULT hr) : result(hr) {} + com_exception(HRESULT hr) noexcept : result(hr) {} const char* what() const override { @@ -111,6 +120,12 @@ namespace DX { if (FAILED(hr)) { +#ifdef _DEBUG + char str[64] = {}; + sprintf_s(str, "**ERROR** Fatal Error with HRESULT of %08X\n", static_cast(hr)); + OutputDebugStringA(str); + __debugbreak(); +#endif throw com_exception(hr); } } diff --git a/Samples/Graphics/PointSprites/readme.docx b/Samples/Graphics/PointSprites/readme.docx index ed285d2..34a7644 100644 Binary files a/Samples/Graphics/PointSprites/readme.docx and b/Samples/Graphics/PointSprites/readme.docx differ diff --git a/Samples/Graphics/SimpleHDR/DeviceResources.cpp b/Samples/Graphics/SimpleHDR/DeviceResources.cpp index eedd70a..9b29c39 100644 --- a/Samples/Graphics/SimpleHDR/DeviceResources.cpp +++ b/Samples/Graphics/SimpleHDR/DeviceResources.cpp @@ -1,6 +1,8 @@ // // DeviceResources.cpp - A wrapper for the Direct3D 12.X device and swapchain // +// Modified to expose a UAV for the swap buffer. +// #include "pch.h" #include "DeviceResources.h" @@ -55,7 +57,7 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } } @@ -83,6 +85,14 @@ void DeviceResources::CreateDeviceResources() params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); #ifdef _GAMING_XBOX_SCARLETT params.CreateDeviceFlags = createDeviceFlags; + +#if (_GXDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif #endif HRESULT hr = D3D12XboxCreateDevice( @@ -118,9 +128,12 @@ void DeviceResources::CreateDeviceResources() rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + m_rtvDescriptorHeap->SetName(L"DeviceResources"); + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + // Create UAV for backbuffer. D3D12_DESCRIPTOR_HEAP_DESC uavDescriptorHeapDesc = {}; uavDescriptorHeapDesc.NumDescriptors = m_backBufferCount; uavDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; @@ -135,6 +148,7 @@ void DeviceResources::CreateDeviceResources() dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + m_dsvDescriptorHeap->SetName(L"DeviceResources"); } @@ -151,11 +165,13 @@ void DeviceResources::CreateDeviceResources() // Create a command list for recording graphics commands. ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_GRAPHICS_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); ThrowIfFailed(m_commandList->Close()); + m_commandList->SetName(L"DeviceResources"); // Create a fence for tracking GPU execution progress. ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); m_fenceValues[m_backBufferIndex]++; + m_fence->SetName(L"DeviceResources"); m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); @@ -231,7 +247,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -245,8 +261,11 @@ void DeviceResources::CreateWindowSizeDependentResources() swapChainBufferDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; #ifdef _GAMING_XBOX_XBOXONE - // For Xbox One, a title needs to specify the auto tone mapping flag, but not on Scarlett - swapChainBufferDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_AUTOMATIC_GAMEDVR_TONE_MAP; + if (m_options & c_EnableHDR) + { + // For Xbox One, a title needs to specify the auto tone mapping flag, but not on Xbox Series X|S + swapChainBufferDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_AUTOMATIC_GAMEDVR_TONE_MAP; + } #endif D3D12_CLEAR_VALUE swapChainOptimizedClearValue = {}; @@ -260,22 +279,22 @@ void DeviceResources::CreateWindowSizeDependentResources() &swapChainBufferDesc, D3D12_RESOURCE_STATE_PRESENT, &swapChainOptimizedClearValue, - IID_GRAPHICS_PPV_ARGS(m_renderTargets[n].ReleaseAndGetAddressOf()))); + IID_GRAPHICS_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); wchar_t name[25] = {}; - swprintf_s(name, L"SwapBuffer %u", n); + swprintf_s(name, L"Render target %u", n); m_renderTargets[n]->SetName(name); D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); - CD3DX12_CPU_DESCRIPTOR_HANDLE uavDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE uavDescriptor( m_uavDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_uavDescriptorSize); @@ -289,7 +308,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -302,7 +321,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -338,10 +357,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -349,7 +364,8 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState); m_commandList->ResourceBarrier(1, &barrier); } @@ -361,7 +377,9 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); m_commandList->ResourceBarrier(1, &barrier); } @@ -392,9 +410,10 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const m_commandQueue->PresentX(1, &planeParameters, params) ); - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -416,13 +435,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -431,25 +450,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/Graphics/SimpleHDR/DeviceResources.h b/Samples/Graphics/SimpleHDR/DeviceResources.h index 4f56d78..223fe56 100644 --- a/Samples/Graphics/SimpleHDR/DeviceResources.h +++ b/Samples/Graphics/SimpleHDR/DeviceResources.h @@ -1,6 +1,8 @@ // // DeviceResources.h - A wrapper for the Direct3D 12.X device and swapchain // +// Modified to expose a UAV for the swap buffer. +// #pragma once @@ -10,9 +12,11 @@ namespace DX class DeviceResources { public: - static constexpr unsigned int c_Enable4K_UHD = 0x1; - static constexpr unsigned int c_EnableQHD = 0x2; - static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_ReverseDepth = 0x8; + static constexpr unsigned int c_AmplificationShaders = 0x10; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -40,6 +44,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -80,7 +85,6 @@ namespace DX } private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; diff --git a/Samples/Graphics/SimpleHDR/Main.cpp b/Samples/Graphics/SimpleHDR/Main.cpp index 9cc14da..9958296 100644 --- a/Samples/Graphics/SimpleHDR/Main.cpp +++ b/Samples/Graphics/SimpleHDR/Main.cpp @@ -1,7 +1,7 @@ //-------------------------------------------------------------------------------------- // Main.cpp // -// Entry point for Microsoft Game Core on Xbox +// Entry point for Microsoft GDK with Xbox extensions // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. @@ -56,7 +56,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp // Default main thread to CPU 0 SetThreadAffinityMask(GetCurrentThread(), 0x1); - // Microsoft Game Core on Xbox supports UTF-8 everywhere + // Microsoft GDKX supports UTF-8 everywhere assert(GetACP() == CP_UTF8); g_sample = std::make_unique(); @@ -111,7 +111,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -171,7 +171,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); sample->OnResuming(); } diff --git a/Samples/Graphics/SimpleHDR/SimpleHDR.cpp b/Samples/Graphics/SimpleHDR/SimpleHDR.cpp index 7147e0d..8feb539 100644 --- a/Samples/Graphics/SimpleHDR/SimpleHDR.cpp +++ b/Samples/Graphics/SimpleHDR/SimpleHDR.cpp @@ -50,7 +50,9 @@ Sample::Sample() noexcept(false) : // On Xbox One, 10:10:10:2 is required for HDR m_deviceResources = std::make_unique(DXGI_FORMAT_R10G10B10A2_UNORM, #endif - DXGI_FORMAT_UNKNOWN, 2, DX::DeviceResources::c_Enable4K_UHD | DX::DeviceResources::c_EnableQHD | DX::DeviceResources::c_EnableHDR); + DXGI_FORMAT_UNKNOWN, + 2, + DX::DeviceResources::c_Enable4K_UHD | DX::DeviceResources::c_EnableQHD | DX::DeviceResources::c_EnableHDR); } // Initialize the Direct3D resources required to run. @@ -67,7 +69,7 @@ void Sample::Initialize(HWND window) CreateWindowSizeDependentResources(); // Try to switch the display into HDR mode - TryEnableHDR(); + SetDisplayMode(); // Render all UI at 1080p so that it's easy to switch between 1080p/1440p/4K auto viewportUI = m_deviceResources->GetScreenViewport(); @@ -82,6 +84,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); @@ -164,12 +168,12 @@ void Sample::Clear() TransitionResource(commandList, m_hdrScene.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_RENDER_TARGET); - auto rtvDescriptor = m_rtvPile->GetCpuHandle(HDRSceneRTV); + auto const rtvDescriptor = m_rtvPile->GetCpuHandle(HDRSceneRTV); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, nullptr); commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -180,11 +184,11 @@ void Sample::RenderUI(ID3D12GraphicsCommandList* commandList) { PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"RenderUI"); - auto rtvDescriptor = m_rtvPile->GetCpuHandle(HDRSceneRTV); + auto const rtvDescriptor = m_rtvPile->GetCpuHandle(HDRSceneRTV); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, nullptr); - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -229,7 +233,7 @@ void Sample::FinalHDRShader(ID3D12GraphicsCommandList* commandList) PIXEndEvent(commandList); } -void Sample::TryEnableHDR() +void Sample::SetDisplayMode() { if ((m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 ) { @@ -256,7 +260,7 @@ void Sample::OnSuspending() void Sample::OnResuming() { // While a title is suspended, the console TV settings could have changed, so we need to call the display APIs when resuming - TryEnableHDR(); + SetDisplayMode(); m_deviceResources->Resume(); m_timer.ResetElapsedTime(); @@ -270,7 +274,7 @@ void Sample::OnConstrained() void Sample::OnUnConstrained() { // While a title is constrained, the console TV settings could have changed, so we need to call the display APIs when unconstraining - TryEnableHDR(); + SetDisplayMode(); } #pragma endregion @@ -285,7 +289,7 @@ void Sample::CreateDeviceDependentResources() // Use a primitive batch to draw a simple triangle { - RenderTargetState rtState(g_hdrBackBufferFormat, m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState rtState(g_hdrBackBufferFormat, m_deviceResources->GetDepthBufferFormat()); m_batch = std::make_unique>(device); EffectPipelineStateDescription pd(&VertexPositionColor::InputLayout, CommonStates::Opaque, diff --git a/Samples/Graphics/SimpleHDR/SimpleHDR.h b/Samples/Graphics/SimpleHDR/SimpleHDR.h index 82d8781..e4a4c6c 100644 --- a/Samples/Graphics/SimpleHDR/SimpleHDR.h +++ b/Samples/Graphics/SimpleHDR/SimpleHDR.h @@ -52,7 +52,7 @@ private: void CreateDeviceDependentResources(); void CreateWindowSizeDependentResources(); - void TryEnableHDR(); + void SetDisplayMode(); // Device resources. std::unique_ptr m_deviceResources; diff --git a/Samples/Graphics/SimpleHDR/StepTimer.h b/Samples/Graphics/SimpleHDR/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/SimpleHDR/StepTimer.h +++ b/Samples/Graphics/SimpleHDR/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/SimpleHDR/pch.h b/Samples/Graphics/SimpleHDR/pch.h index 8ba561c..28f8814 100644 --- a/Samples/Graphics/SimpleHDR/pch.h +++ b/Samples/Graphics/SimpleHDR/pch.h @@ -37,8 +37,8 @@ #include -#if _GXDK_VER < 0x4A610F3C /* GDK Edition 200800 */ -#error This sample requires the August 2020 GDK or later +#if _GXDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -69,6 +69,7 @@ #include #include #include +#include #include #include diff --git a/Samples/Graphics/SimpleMeshlet/DeviceResources.cpp b/Samples/Graphics/SimpleMeshlet/DeviceResources.cpp index 81b00e1..2b40774 100644 --- a/Samples/Graphics/SimpleMeshlet/DeviceResources.cpp +++ b/Samples/Graphics/SimpleMeshlet/DeviceResources.cpp @@ -12,7 +12,6 @@ using namespace DX; using Microsoft::WRL::ComPtr; -#ifdef _GAMING_DESKTOP #ifdef __clang__ #pragma clang diagnostic ignored "-Wcovered-switch-default" #pragma clang diagnostic ignored "-Wswitch-enum" @@ -20,6 +19,7 @@ using Microsoft::WRL::ComPtr; #pragma warning(disable : 4061) +#ifdef _GAMING_DESKTOP namespace { inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) noexcept @@ -39,7 +39,8 @@ namespace DeviceResources::DeviceResources( DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, - UINT backBufferCount) noexcept(false) : + UINT backBufferCount, + unsigned int flags) noexcept(false) : m_backBufferIndex(0), m_fenceValues{}, #ifdef _GAMING_XBOX @@ -54,6 +55,7 @@ DeviceResources::DeviceResources( m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_0), m_outputSize{ 0, 0, 1, 1 }, + m_options(flags), m_deviceNotify(nullptr) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) @@ -72,7 +74,7 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } #endif } @@ -98,6 +100,14 @@ void DeviceResources::CreateDeviceResources() params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#if defined(_GAMING_XBOX_SCARLETT) && (_GRDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif + HRESULT hr = D3D12XboxCreateDevice( nullptr, ¶ms, @@ -328,7 +338,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -360,7 +370,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -371,7 +381,7 @@ void DeviceResources::CreateWindowSizeDependentResources() #else // _GAMING_DESKTOP - DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + const DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); // If the swap chain already exists, resize it, otherwise create one. if (m_swapChain) @@ -454,7 +464,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -469,7 +479,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -482,7 +492,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -593,12 +603,6 @@ void DeviceResources::HandleDeviceLost() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { -#ifdef _GAMING_XBOX - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); -#endif - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -606,7 +610,8 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState); m_commandList->ResourceBarrier(1, &barrier); } @@ -618,7 +623,9 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); m_commandList->ResourceBarrier(1, &barrier); } @@ -638,9 +645,12 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) m_commandQueue->PresentX(1, &planeParameters, nullptr) ); - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. -#else + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + +#else // _GAMING_DESKTOP // The first argument instructs DXGI to block until VSync, putting the application // to sleep until the next VSync. This ensures we don't waste any cycles rendering @@ -663,9 +673,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) ThrowIfFailed(hr); } -#endif - MoveToNextFrame(); +#endif } // Handle GPU suspend/resume @@ -691,13 +700,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -706,32 +715,20 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() -{ - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. #ifdef _GAMING_XBOX - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; -#else - m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); -#endif - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() +{ + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } -#ifdef _GAMING_XBOX // Set frame interval and register for frame events void DeviceResources::RegisterFrameEvents() { @@ -760,7 +757,30 @@ void DeviceResources::RegisterFrameEvents() nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE)); } -#else + +#else // _GAMING_DESKTOP + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + // This method acquires the first available hardware adapter that supports Direct3D 12. // If no such adapter can be found, try WARP. Otherwise throw an exception. void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) diff --git a/Samples/Graphics/SimpleMeshlet/DeviceResources.h b/Samples/Graphics/SimpleMeshlet/DeviceResources.h index a920f13..0e0aeb0 100644 --- a/Samples/Graphics/SimpleMeshlet/DeviceResources.h +++ b/Samples/Graphics/SimpleMeshlet/DeviceResources.h @@ -22,9 +22,13 @@ namespace DX class DeviceResources { public: + static constexpr unsigned int c_ReverseDepth = 0x1; + static constexpr unsigned int c_AmplificationShaders = 0x2; + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, - UINT backBufferCount = 2) noexcept(false); + UINT backBufferCount = 2, + unsigned int flags = 0) noexcept(false); ~DeviceResources(); DeviceResources(DeviceResources&&) = default; @@ -45,6 +49,9 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; +#ifdef _GAMING_XBOX + void WaitForOrigin(); +#endif // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -68,6 +75,7 @@ namespace DX D3D12_RECT GetScissorRect() const noexcept { return m_scissorRect; } UINT GetCurrentFrameIndex() const noexcept { return m_backBufferIndex; } UINT GetBackBufferCount() const noexcept { return m_backBufferCount; } + unsigned int GetDeviceOptions() const noexcept { return m_options; } CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const noexcept { @@ -81,10 +89,10 @@ namespace DX } private: - void MoveToNextFrame(); #ifdef _GAMING_XBOX void RegisterFrameEvents(); #else + void MoveToNextFrame(); void GetAdapter(IDXGIAdapter1** ppAdapter); #endif @@ -131,6 +139,9 @@ namespace DX D3D_FEATURE_LEVEL m_d3dFeatureLevel; RECT m_outputSize; + // DeviceResources options (see flags above) + unsigned int m_options; + // The IDeviceNotify can be held directly as it owns the DeviceResources. IDeviceNotify* m_deviceNotify; }; diff --git a/Samples/Graphics/SimpleMeshlet/Main.cpp b/Samples/Graphics/SimpleMeshlet/Main.cpp index 30a03d1..76e9d21 100644 --- a/Samples/Graphics/SimpleMeshlet/Main.cpp +++ b/Samples/Graphics/SimpleMeshlet/Main.cpp @@ -63,7 +63,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp if (hr == E_GAMERUNTIME_DLL_NOT_FOUND || hr == E_GAMERUNTIME_VERSION_MISMATCH) { #ifdef _GAMING_DESKTOP - (void)MessageBoxW(nullptr, L"Game Runtime is not installed on this system or needs updating.", g_szAppName, MB_ICONERROR | MB_OK); + std::ignore = MessageBoxW(nullptr, L"Game Runtime is not installed on this system or needs updating.", g_szAppName, MB_ICONERROR | MB_OK); #endif } return 1; @@ -142,7 +142,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -240,7 +240,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); sample->OnResuming(); } @@ -254,7 +254,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) else { PAINTSTRUCT ps; - (void)BeginPaint(hWnd, &ps); + std::ignore = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); } break; @@ -369,7 +369,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); diff --git a/Samples/Graphics/SimpleMeshlet/ReadMe.docx b/Samples/Graphics/SimpleMeshlet/ReadMe.docx index 3bae784..6afa802 100644 Binary files a/Samples/Graphics/SimpleMeshlet/ReadMe.docx and b/Samples/Graphics/SimpleMeshlet/ReadMe.docx differ diff --git a/Samples/Graphics/SimpleMeshlet/SimpleMeshlet.cpp b/Samples/Graphics/SimpleMeshlet/SimpleMeshlet.cpp index 7fbedae..3ce0fd8 100644 --- a/Samples/Graphics/SimpleMeshlet/SimpleMeshlet.cpp +++ b/Samples/Graphics/SimpleMeshlet/SimpleMeshlet.cpp @@ -44,7 +44,7 @@ namespace const wchar_t* s_meshFilenames[] = { -#if _GAMING_DESKTOP +#ifdef _GAMING_DESKTOP L"ATGDragon\\Dragon_LOD0.sdkmesh", L"ATGDragon\\Dragon_LOD1.sdkmesh", L"ATGDragon\\Dragon_LOD2.sdkmesh", @@ -63,8 +63,8 @@ namespace #endif }; - const uint32_t s_dragonLODStart = 0; - const uint32_t s_dragonLODCount = 6; + constexpr uint32_t s_dragonLODStart = 0; + constexpr uint32_t s_dragonLODCount = 6; struct ObjectDefinition { @@ -88,8 +88,7 @@ namespace } Sample::Sample() noexcept(false) - : m_deviceResources(std::make_unique()) - , m_displayWidth(0) + : m_displayWidth(0) , m_displayHeight(0) , m_frame(0) , m_cull(false) @@ -97,6 +96,7 @@ Sample::Sample() noexcept(false) , m_drawMeshlets(true) , m_lodIndex(s_dragonLODStart) { + m_deviceResources = std::make_unique(); m_deviceResources->RegisterDeviceNotify(this); } @@ -112,7 +112,9 @@ Sample::~Sample() void Sample::Initialize(HWND window, int width, int height) { m_gamePad = std::make_unique(); + m_keyboard = std::make_unique(); + m_mouse = std::make_unique(); m_mouse->SetWindow(window); @@ -131,6 +133,10 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); +#ifdef _GAMING_XBOX + m_deviceResources->WaitForOrigin(); +#endif + m_timer.Tick([&]() { Update(m_timer); @@ -279,8 +285,8 @@ void Sample::Render() UpdateConstants(commandList); // Set up the root signature & pipeline state - ID3D12DescriptorHeap* descriptorHeaps[] = { m_srvPile->Heap() }; - commandList->SetDescriptorHeaps(1, descriptorHeaps); + auto descriptorHeaps = m_srvPile->Heap(); + commandList->SetDescriptorHeaps(1, &descriptorHeaps); commandList->SetGraphicsRootSignature(m_rootSignature.Get()); commandList->SetPipelineState(m_cull ? m_cullMeshletPso.Get() : m_basicMeshletPso.Get()); @@ -381,16 +387,16 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -401,7 +407,7 @@ void Sample::DrawHUD(ID3D12GraphicsCommandList* commandList) { m_hudBatch->Begin(commandList); - auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(m_displayWidth, m_displayHeight); + auto const safe = SimpleMath::Viewport::ComputeTitleSafeArea(m_displayWidth, m_displayHeight); wchar_t textBuffer[128] = {}; XMFLOAT2 textPos = XMFLOAT2(float(safe.left), float(safe.top)); @@ -482,14 +488,6 @@ void Sample::DrawHUD(ID3D12GraphicsCommandList* commandList) #pragma region Message Handlers // Message handlers -void Sample::OnActivated() -{ -} - -void Sample::OnDeactivated() -{ -} - void Sample::OnSuspending() { m_deviceResources->Suspend(); @@ -505,7 +503,7 @@ void Sample::OnResuming() void Sample::OnWindowMoved() { - auto r = m_deviceResources->GetOutputSize(); + auto const r = m_deviceResources->GetOutputSize(); m_deviceResources->WindowSizeChanged(r.right, r.bottom); } @@ -554,15 +552,13 @@ void Sample::CreateDeviceDependentResources() // Create heap m_srvPile = std::make_unique(device, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 128, DescriptorHeapIndex::SRV_Count); m_frustumDraw.CreateDeviceResources(*m_deviceResources, *m_commonStates); { - auto defaultHeapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES defaultHeapProps(D3D12_HEAP_TYPE_DEFAULT); auto cbDesc = CD3DX12_RESOURCE_DESC::Buffer(GetAlignedSize(sizeof(Constants))); DX::ThrowIfFailed(device->CreateCommittedResource( @@ -619,12 +615,12 @@ void Sample::CreateDeviceDependentResources() for (size_t i = 0; i < m_models.size(); ++i) { - wchar_t filepath[256]; - DX::FindMediaFile(filepath, _countof(filepath), s_meshFilenames[i]); + wchar_t filepath[_MAX_PATH] = {}; + DX::FindMediaFile(filepath, _MAX_PATH, s_meshFilenames[i]); m_models[i].Model = Model::CreateFromSDKMESH(device, filepath); - wchar_t meshletFilepath[256] = {}; + wchar_t meshletFilepath[_MAX_PATH] = {}; swprintf_s(meshletFilepath, L"%s.bin", filepath); m_models[i].MeshletData = MeshletSet::Read(meshletFilepath); @@ -661,7 +657,7 @@ void Sample::CreateDeviceDependentResources() auto effectFactory = EffectFactory(m_srvPile->Heap(), m_commonStates->Heap()); - auto objectRTState = RenderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState objectRTState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); auto objectPSD = EffectPipelineStateDescription( nullptr, CommonStates::Opaque, @@ -680,7 +676,7 @@ void Sample::CreateDeviceDependentResources() m_scene[i].ModelIndex = index; m_scene[i].Effects = m_models[index].Model->CreateEffects(effectFactory, objectPSD, objectPSD, int(texOffsets[index])); - auto defaultHeapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES defaultHeapProps(D3D12_HEAP_TYPE_DEFAULT); auto cbDesc = CD3DX12_RESOURCE_DESC::Buffer(GetAlignedSize(sizeof(Instance))); DX::ThrowIfFailed(device->CreateCommittedResource( &defaultHeapProps, @@ -693,7 +689,7 @@ void Sample::CreateDeviceDependentResources() } // HUD - auto backBufferRts = RenderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState backBufferRts(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); auto spritePSD = SpriteBatchPipelineStateDescription(backBufferRts, &CommonStates::AlphaBlend); m_hudBatch = std::make_unique(device, resourceUpload, spritePSD); @@ -716,7 +712,7 @@ void Sample::CreateDeviceDependentResources() // Allocate all memory resources that change on a window SizeChanged event. void Sample::CreateWindowSizeDependentResources() { - RECT size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); m_displayWidth = size.right - size.left; m_displayHeight = size.bottom - size.top; @@ -747,16 +743,19 @@ void Sample::CreateWindowSizeDependentResources() void Sample::OnDeviceLost() { - m_graphicsMemory.reset(); + m_commonStates.reset(); m_srvPile.reset(); m_rootSignature.Reset(); m_basicMeshletPso.Reset(); m_cullMeshletPso.Reset(); + m_viewCB.Reset(); m_hudBatch.reset(); m_smallFont.reset(); - m_models.resize(0); + m_models.clear(); m_textureFactory.reset(); - m_scene.resize(0); + m_scene.clear(); + m_frustumDraw.ReleaseResources(); + m_graphicsMemory.reset(); } void Sample::OnDeviceRestored() diff --git a/Samples/Graphics/SimpleMeshlet/SimpleMeshlet.h b/Samples/Graphics/SimpleMeshlet/SimpleMeshlet.h index df699fd..40e677a 100644 --- a/Samples/Graphics/SimpleMeshlet/SimpleMeshlet.h +++ b/Samples/Graphics/SimpleMeshlet/SimpleMeshlet.h @@ -54,8 +54,8 @@ public: void OnDeviceRestored() override; // Messages - void OnActivated(); - void OnDeactivated(); + void OnActivated() {} + void OnDeactivated() {} void OnSuspending(); void OnResuming(); void OnWindowMoved(); diff --git a/Samples/Graphics/SimpleMeshlet/StepTimer.h b/Samples/Graphics/SimpleMeshlet/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/SimpleMeshlet/StepTimer.h +++ b/Samples/Graphics/SimpleMeshlet/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/SimpleMeshlet/pch.h b/Samples/Graphics/SimpleMeshlet/pch.h index 69c1d20..fb109bc 100644 --- a/Samples/Graphics/SimpleMeshlet/pch.h +++ b/Samples/Graphics/SimpleMeshlet/pch.h @@ -41,8 +41,8 @@ #include -#if _GRDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GRDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -81,6 +81,7 @@ #include #include #include +#include #ifdef _GAMING_XBOX #include @@ -93,23 +94,24 @@ #include #include "CommonStates.h" -#include "ControllerFont.h" #include "DescriptorHeap.h" #include "DirectXHelpers.h" #include "GamePad.h" #include "GraphicsMemory.h" #include "Keyboard.h" -#include "Meshlet.h" #include "Model.h" #include "Mouse.h" -#include "OrbitCamera.h" -#include "ReadData.h" #include "RenderTargetState.h" #include "ResourceUploadBatch.h" #include "SimpleMath.h" #include "SpriteBatch.h" #include "SpriteFont.h" +#include "ControllerFont.h" +#include "Meshlet.h" +#include "OrbitCamera.h" +#include "ReadData.h" + namespace DX { // Helper class for COM exceptions diff --git a/Samples/Graphics/SimplePBR/DeviceResources.cpp b/Samples/Graphics/SimplePBR/DeviceResources.cpp index 0bf5d85..ec2ddaa 100644 --- a/Samples/Graphics/SimplePBR/DeviceResources.cpp +++ b/Samples/Graphics/SimplePBR/DeviceResources.cpp @@ -21,7 +21,6 @@ using Microsoft::WRL::ComPtr; #pragma warning(disable : 4061) #ifdef _GAMING_DESKTOP - namespace { inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) noexcept @@ -48,7 +47,8 @@ namespace DeviceResources::DeviceResources( DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, - UINT backBufferCount) noexcept(false) : + UINT backBufferCount, + unsigned int flags) noexcept(false) : m_backBufferIndex(0), m_fenceValues{}, #ifdef _GAMING_XBOX @@ -67,7 +67,8 @@ DeviceResources::DeviceResources( #endif m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_0), - m_outputSize{ 0, 0, 1920, 1080 }, + m_outputSize{ 0, 0, 1, 1 }, + m_options(flags), m_deviceNotify(nullptr) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) @@ -86,13 +87,12 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } #endif } // Configures the Direct3D device, and stores handles to it and the device context. - void DeviceResources::CreateDeviceResources() { #ifdef _GAMING_XBOX @@ -113,6 +113,14 @@ void DeviceResources::CreateDeviceResources() params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#if defined(_GAMING_XBOX_SCARLETT) && (_GRDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif + HRESULT hr = D3D12XboxCreateDevice( nullptr, ¶ms, @@ -133,7 +141,7 @@ void DeviceResources::CreateDeviceResources() m_d3dFeatureLevel = D3D_FEATURE_LEVEL_12_0; -#else +#else // _GAMING_DESKTOP #if defined(_DEBUG) // Enable the debug layer (requires the Graphics Tools "optional feature"). @@ -212,6 +220,9 @@ void DeviceResources::CreateDeviceResources() // Determine maximum supported feature level for this device static const D3D_FEATURE_LEVEL s_featureLevels[] = { +#if defined(NTDDI_WIN10_FE) && (NTDDI_VERSION >= NTDDI_WIN10_FE) + D3D_FEATURE_LEVEL_12_2, +#endif D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, D3D_FEATURE_LEVEL_11_1, @@ -297,7 +308,7 @@ void DeviceResources::CreateDeviceResources() { throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } - + #ifdef _GAMING_XBOX RegisterFrameEvents(); #endif @@ -337,7 +348,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -369,7 +380,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -395,7 +406,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_gameDVRFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(m_backBufferCount + n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargetsGameDVR[n].Get(), &rtvDesc, rtvDescriptorGameDVR); @@ -404,9 +415,9 @@ void DeviceResources::CreateWindowSizeDependentResources() // Reset the index to the current back buffer. m_backBufferIndex = 0; -#else +#else // _GAMING_DESKTOP - DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + const DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); // If the swap chain already exists, resize it, otherwise create one. if (m_swapChain) @@ -492,7 +503,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -507,7 +518,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -520,7 +531,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -566,7 +577,7 @@ void DeviceResources::SetWindow(HWND window, int width, int height) noexcept // This method is called when the Win32 window changes size. bool DeviceResources::WindowSizeChanged(int width, int height) { - RECT newRc = {0,0,0,0}; + RECT newRc; newRc.left = newRc.top = 0; newRc.right = width; newRc.bottom = height; @@ -636,30 +647,25 @@ void DeviceResources::HandleDeviceLost() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { -#ifdef _GAMING_XBOX - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); -#endif - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); if (beforeState != afterState) { + // Transition the render target into the correct state to allow for drawing into it. #ifdef _GAMING_XBOX - - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), - beforeState, afterState), - }; - m_commandList->ResourceBarrier(static_cast(std::size(barriers)), barriers); + const D3D12_RESOURCE_BARRIER barriers[2] = + { + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + beforeState, afterState), + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), + beforeState, afterState), + }; + m_commandList->ResourceBarrier(static_cast(std::size(barriers)), barriers); #else - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState); m_commandList->ResourceBarrier(1, &barrier); #endif @@ -673,7 +679,7 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) { // Transition the render target to the state that allows it to be presented to the display. #ifdef _GAMING_XBOX - D3D12_RESOURCE_BARRIER barriers[2] = + const D3D12_RESOURCE_BARRIER barriers[2] = { CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), @@ -681,7 +687,9 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) m_commandList->ResourceBarrier(_countof(barriers), barriers); #else // Transition the render target to the state that allows it to be presented to the display. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); m_commandList->ResourceBarrier(1, &barrier); #endif } @@ -691,6 +699,7 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); #ifdef _GAMING_XBOX + // Present the backbuffer using the PresentX API. D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters[2] = {}; planeParameters[0].Token = planeParameters[1].Token = m_framePipelineToken; @@ -705,7 +714,14 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) ThrowIfFailed( m_commandQueue->PresentX(2, planeParameters, nullptr) ); -#else + + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + +#else // _GAMING_DESKTOP + HRESULT hr = m_swapChain->Present(1, 0); // If the device was reset we must completely reinitialize the renderer. if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) @@ -723,11 +739,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) ThrowIfFailed(hr); } -#endif - MoveToNextFrame(); -#ifdef _GAMING_DESKTOP if (!m_dxgiFactory->IsCurrent()) { UpdateColorSpace(); @@ -758,13 +771,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -773,32 +786,20 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() -{ - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. #ifdef _GAMING_XBOX - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; -#else - m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); -#endif - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() +{ + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } -#ifdef _GAMING_XBOX // Set frame interval and register for frame events void DeviceResources::RegisterFrameEvents() { @@ -827,7 +828,30 @@ void DeviceResources::RegisterFrameEvents() nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE)); } -#else + +#else // _GAMING_DESKTOP + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + // This method acquires the first available hardware adapter that supports Direct3D 12. // If no such adapter can be found, try WARP. Otherwise throw an exception. void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) @@ -883,9 +907,6 @@ void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) *ppAdapter = adapter.Detach(); } -#endif - -#ifdef _GAMING_DESKTOP // Sets the color space for the swap chain in order to handle HDR output. void DeviceResources::UpdateColorSpace() @@ -994,5 +1015,4 @@ void DeviceResources::UpdateColorSpace() } } -#endif // _GAMING_DESKTOP - +#endif diff --git a/Samples/Graphics/SimplePBR/DeviceResources.h b/Samples/Graphics/SimplePBR/DeviceResources.h index e3c80e7..9809b06 100644 --- a/Samples/Graphics/SimplePBR/DeviceResources.h +++ b/Samples/Graphics/SimplePBR/DeviceResources.h @@ -21,9 +21,13 @@ namespace DX class DeviceResources { public: + static constexpr unsigned int c_ReverseDepth = 0x1; + static constexpr unsigned int c_AmplificationShaders = 0x2; + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, - UINT backBufferCount = 2) noexcept(false); + UINT backBufferCount = 2, + unsigned int flags = 0) noexcept(false); ~DeviceResources(); DeviceResources(DeviceResources&&) = default; @@ -44,8 +48,9 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; - -#ifdef _GAMING_DESKTOP +#ifdef _GAMING_XBOX + void WaitForOrigin(); +#else void UpdateColorSpace(); #endif @@ -73,6 +78,7 @@ namespace DX D3D12_RECT GetScissorRect() const noexcept { return m_scissorRect; } UINT GetCurrentFrameIndex() const noexcept { return m_backBufferIndex; } UINT GetBackBufferCount() const noexcept { return m_backBufferCount; } + unsigned int GetDeviceOptions() const noexcept { return m_options; } CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const noexcept { @@ -98,12 +104,13 @@ namespace DX } #endif private: - void MoveToNextFrame(); #ifdef _GAMING_XBOX void RegisterFrameEvents(); #else + void MoveToNextFrame(); void GetAdapter(IDXGIAdapter1** ppAdapter); #endif + static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; UINT m_backBufferIndex; @@ -161,6 +168,9 @@ namespace DX D3D_FEATURE_LEVEL m_d3dFeatureLevel; RECT m_outputSize; + // DeviceResources options (see flags above) + unsigned int m_options; + // The IDeviceNotify can be held directly as it owns the DeviceResources. IDeviceNotify* m_deviceNotify; }; diff --git a/Samples/Graphics/SimplePBR/Main.cpp b/Samples/Graphics/SimplePBR/Main.cpp index ee7ace0..a2cd7d4 100644 --- a/Samples/Graphics/SimplePBR/Main.cpp +++ b/Samples/Graphics/SimplePBR/Main.cpp @@ -137,8 +137,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp #endif break; - case XSystemDeviceType::XboxOneXDevkit: case XSystemDeviceType::XboxScarlettAnaconda /* Xbox Series X */: + case XSystemDeviceType::XboxOneXDevkit: case XSystemDeviceType::XboxScarlettDevkit: default: rc = { 0, 0, 3840, 2160 }; @@ -163,9 +163,11 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp return 1; ShowWindow(hwnd, nCmdShow); + #ifdef _GAMING_XBOX SetDisplayMode(); #endif + SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(g_sample.get())); // Sample Usage Telemetry @@ -482,13 +484,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // HDR helper void SetDisplayMode() noexcept { - // Request HDR mode. - auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); + // Request HDR mode. + auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); - g_HDRMode = (result == XDisplayHdrModeResult::Enabled); + g_HDRMode = (result == XDisplayHdrModeResult::Enabled); #ifdef _DEBUG - OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); + OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); #endif } #endif diff --git a/Samples/Graphics/SimplePBR/Readme.docx b/Samples/Graphics/SimplePBR/Readme.docx index 23a4942..cac3901 100644 Binary files a/Samples/Graphics/SimplePBR/Readme.docx and b/Samples/Graphics/SimplePBR/Readme.docx differ diff --git a/Samples/Graphics/SimplePBR/SimplePBR.cpp b/Samples/Graphics/SimplePBR/SimplePBR.cpp index eb4acfe..172f49e 100644 --- a/Samples/Graphics/SimplePBR/SimplePBR.cpp +++ b/Samples/Graphics/SimplePBR/SimplePBR.cpp @@ -1,7 +1,7 @@ //-------------------------------------------------------------------------------------- // SimplePBR.cpp // -// Demonstrates PBRModel and PBREffect in DirectX 12 on Xbox One, Scarlett and PC devices +// Demonstrates PBRModel and PBREffect in DirectX 12 on Xbox One, Xbox Series X|S, and PC devices // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. @@ -9,7 +9,8 @@ #include "pch.h" #include "SimplePBR.h" -#include + +#include "ATGColors.h" #include "FindMedia.h" #include "ControllerFont.h" @@ -21,6 +22,10 @@ using Microsoft::WRL::ComPtr; namespace { + constexpr DXGI_FORMAT c_HDRFormat = DXGI_FORMAT_R11G11B10_FLOAT; + constexpr DXGI_FORMAT c_backBufferFormat = DXGI_FORMAT_R10G10B10A2_UNORM; + constexpr DXGI_FORMAT c_depthFormat = DXGI_FORMAT_D32_FLOAT; + // PBR Assest paths. const wchar_t* s_modelPaths[] = { @@ -50,7 +55,7 @@ namespace D3D12_GPU_DESCRIPTOR_HANDLE irradianceTex, D3D12_GPU_DESCRIPTOR_HANDLE sampler) { - RenderTargetState hdrBufferRts(Sample::GetHDRRenderFormat(), Sample::GetDepthFormat()); + const RenderTargetState hdrBufferRts(c_HDRFormat, c_depthFormat); m_sphere = DirectX::GeometricPrimitive::CreateSphere(1.5); @@ -83,8 +88,8 @@ namespace void XM_CALLCONV Render(ID3D12GraphicsCommandList* commandList, FXMMATRIX camView, CXMMATRIX camProj) { - const size_t numSpheres = 3; - const float step = 15.f; + constexpr size_t numSpheres = 3; + constexpr float step = 15.f; Vector3 modelPos((-step * (numSpheres - 1)) / 2.f, 0, 0); @@ -134,10 +139,10 @@ Sample::Sample() : m_gamepadConnected(false) { m_deviceResources = std::make_unique( - GetBackBufferFormat(), GetDepthFormat(), 2); + c_backBufferFormat, c_depthFormat, 2); m_deviceResources->RegisterDeviceNotify(this); m_gamePad = std::make_unique(); - m_hdrScene = std::make_unique(Sample::GetHDRRenderFormat()); + m_hdrScene = std::make_unique(c_HDRFormat); } Sample::~Sample() @@ -151,16 +156,6 @@ Sample::~Sample() // Initialize the Direct3D resources required to run. void Sample::Initialize(HWND window, int width, int height) { -#ifdef _GAMING_XBOX - // Determine if attached display is HDR or SDR, if HDR, also set the TV in HDR mode. - auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); - - m_bIsTVInHDRMode = (result == XDisplayHdrModeResult::Enabled); -#ifdef _DEBUG - OutputDebugStringA((m_bIsTVInHDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); -#endif -#endif - m_deviceResources->SetWindow(window, width, height); m_deviceResources->CreateDeviceResources(); @@ -169,7 +164,7 @@ void Sample::Initialize(HWND window, int width, int height) // Initialize Camera { const auto size = m_deviceResources->GetOutputSize(); - const float fovAngleY = 70.0f * XM_PI / 180.0f; + constexpr float fovAngleY = 70.0f * XM_PI / 180.0f; m_camera = std::make_unique(); m_camera->SetWindow(size.right, size.bottom); @@ -196,6 +191,10 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); +#ifdef _GAMING_XBOX + m_deviceResources->WaitForOrigin(); +#endif + m_timer.Tick([&]() { Update(m_timer); @@ -268,8 +267,7 @@ void Sample::Update(DX::StepTimer const& timer) void Sample::RenderHUD(ID3D12GraphicsCommandList* commandList) { - DX::DeviceResources* deviceResources = m_deviceResources.get(); - auto size = deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); // Safe area dimensions are in screenspace, with y-axis inverted. auto safe = SimpleMath::Viewport::ComputeTitleSafeArea((UINT)size.right, (UINT)size.bottom); @@ -296,13 +294,13 @@ void Sample::RenderHUD(ID3D12GraphicsCommandList* commandList) float padding = 0.02f; // Convert screenspace coordinates to NDC. - float minX = 2.0f * (safe.left / (FLOAT)size.right) - 1.0f - padding; - float maxX = 2.0f * ((XMVectorGetX(LegendStringBounds) + (FLOAT)safe.left) / (FLOAT)size.right) - 1.0f + padding; - float minYTitle = (2.0f * ((XMVectorGetY(TitleStringBounds) + (FLOAT)safe.top) / (FLOAT)size.bottom) - 1.0f) * -1.0f - padding; - float maxYTitle = (2.0f * (safe.top / (FLOAT)size.bottom) - 1.0f) * -1.0f + padding; + float minX = 2.0f * (safe.left / (float)size.right) - 1.0f - padding; + float maxX = 2.0f * ((XMVectorGetX(LegendStringBounds) + (float)safe.left) / (float)size.right) - 1.0f + padding; + float minYTitle = (2.0f * ((XMVectorGetY(TitleStringBounds) + (float)safe.top) / (float)size.bottom) - 1.0f) * -1.0f - padding; + float maxYTitle = (2.0f * (safe.top / (float)size.bottom) - 1.0f) * -1.0f + padding; - float minYControls = (2.0f * (safe.bottom / (FLOAT)size.bottom) - 1.0f) * -1.0f - padding; - float maxYControls = (2.0f * (((FLOAT)safe.bottom - XMVectorGetY(LegendStringBounds)) / (FLOAT)size.bottom) - 1.0f) * -1.0f + padding; + float minYControls = (2.0f * (safe.bottom / (float)size.bottom) - 1.0f) * -1.0f - padding; + float maxYControls = (2.0f * (((float)safe.bottom - XMVectorGetY(LegendStringBounds)) / (float)size.bottom) - 1.0f) * -1.0f + padding; // Sample Title UI Rectangle VertexPositionColor vTitle0(Vector3(minX, maxYTitle, UIRectangleSceneDepth), UIBackground); @@ -325,9 +323,9 @@ void Sample::RenderHUD(ID3D12GraphicsCommandList* commandList) m_hudBatch->Begin(commandList); #ifdef _GAMING_XBOX - auto fontColor = ATG::ColorsHDR::White; + auto fontColor = ATG::ColorsHDR::White; #else - auto fontColor = ATG::ColorsHDR::LightGrey; + auto fontColor = ATG::ColorsHDR::LightGrey; #endif m_smallFont->DrawString(m_hudBatch.get(), L"SimplePBR Sample", @@ -358,12 +356,11 @@ void Sample::Render() m_deviceResources->Prepare(); Clear(); - DX::DeviceResources* deviceResources = m_deviceResources.get(); - auto commandList = deviceResources->GetCommandList(); + auto commandList = m_deviceResources->GetCommandList(); // Set descriptor heaps ID3D12DescriptorHeap* heaps[] = { m_srvPile->Heap(), m_commonStates->Heap() }; - commandList->SetDescriptorHeaps(_countof(heaps), heaps); + commandList->SetDescriptorHeaps(static_cast(std::size(heaps)), heaps); PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); @@ -372,7 +369,7 @@ void Sample::Render() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render HDR"); - auto depthStencilDescriptor = deviceResources->GetDepthStencilView(); + auto depthStencilDescriptor = m_deviceResources->GetDepthStencilView(); auto toneMapRTVDescriptor = m_rtvHeap->GetFirstCpuHandle(); commandList->OMSetRenderTargets(1, &toneMapRTVDescriptor, FALSE, &depthStencilDescriptor); @@ -406,7 +403,7 @@ void Sample::Render() #if defined(_GAMING_XBOX) // Generate both HDR10 and tonemapped SDR signal - D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptors[2] = { deviceResources->GetRenderTargetView(), deviceResources->GetGameDVRRenderTargetView() }; + D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptors[2] = { m_deviceResources->GetRenderTargetView(), m_deviceResources->GetGameDVRRenderTargetView() }; commandList->OMSetRenderTargets(2, rtvDescriptors, FALSE, nullptr); m_HDR10->SetHDRSourceTexture(m_srvPile->GetGpuHandle(static_cast(StaticDescriptors::SceneTex))); @@ -414,10 +411,10 @@ void Sample::Render() #else { - auto rtv = static_cast(deviceResources->GetRenderTargetView()); + auto rtv = static_cast(m_deviceResources->GetRenderTargetView()); commandList->OMSetRenderTargets(1, &rtv, FALSE, NULL); - if (deviceResources->GetColorSpace() == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) + if (m_deviceResources->GetColorSpace() == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) { // HDR10 signal m_HDR10->SetHDRSourceTexture(m_srvPile->GetGpuHandle(static_cast(StaticDescriptors::SceneTex))); @@ -470,14 +467,6 @@ void Sample::Clear() #pragma region Message Handlers // Message handlers -void Sample::OnActivated() -{ -} - -void Sample::OnDeactivated() -{ -} - void Sample::OnSuspending() { m_deviceResources->Suspend(); @@ -485,11 +474,6 @@ void Sample::OnSuspending() void Sample::OnResuming() { -#ifdef _GAMING_XBOX - // While a title is suspended, the console TV settings could have changed, so we need to call the display APIs when resuming - auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); - m_bIsTVInHDRMode = (result == XDisplayHdrModeResult::Enabled); -#endif m_deviceResources->Resume(); m_timer.ResetElapsedTime(); #ifdef _GAMING_DESKTOP @@ -499,7 +483,7 @@ void Sample::OnResuming() void Sample::OnWindowMoved() { - auto r = m_deviceResources->GetOutputSize(); + auto const r = m_deviceResources->GetOutputSize(); m_deviceResources->WindowSizeChanged(r.right, r.bottom); } @@ -562,7 +546,7 @@ void Sample::CreateDeviceDependentResources() // UI Geometry Setup m_vertexBatch = std::make_unique>(device); - RenderTargetState UIRectRtState(GetHDRRenderFormat(), GetDepthFormat()); + const RenderTargetState UIRectRtState(c_HDRFormat, c_depthFormat); EffectPipelineStateDescription UIRectPd( &VertexType::InputLayout, @@ -573,7 +557,7 @@ void Sample::CreateDeviceDependentResources() m_basicEffect = std::make_unique(device, EffectFlags::VertexColor, UIRectPd); - RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), + const RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); // Begin uploading texture resources @@ -608,7 +592,7 @@ void Sample::CreateDeviceDependentResources() // Pipeline state - for rendering direct to back buffer { - RenderTargetState backBufferRts(Sample::GetBackBufferFormat(), Sample::GetDepthFormat()); + RenderTargetState backBufferRts(c_backBufferFormat, c_depthFormat); // Create HDR10 color space effect #if defined(_GAMING_XBOX) @@ -630,7 +614,7 @@ void Sample::CreateDeviceDependentResources() // Pipeline state - for rendering to HDR buffer { - RenderTargetState hdrBufferRts(Sample::GetHDRRenderFormat(), Sample::GetDepthFormat()); + const RenderTargetState hdrBufferRts(c_HDRFormat, c_depthFormat); // HUD DirectX::SpriteBatchPipelineStateDescription hudpd( diff --git a/Samples/Graphics/SimplePBR/SimplePBR.h b/Samples/Graphics/SimplePBR/SimplePBR.h index 5f8c45f..bf6c663 100644 --- a/Samples/Graphics/SimplePBR/SimplePBR.h +++ b/Samples/Graphics/SimplePBR/SimplePBR.h @@ -44,8 +44,8 @@ public: void OnDeviceRestored() override; // Messages - void OnActivated(); - void OnDeactivated(); + void OnActivated() {} + void OnDeactivated() {} void OnSuspending(); void OnResuming(); void OnConstrained() {} @@ -57,10 +57,6 @@ public: // Properties void GetDefaultSize(int& width, int& height) const noexcept; - inline static DXGI_FORMAT GetHDRRenderFormat() { return DXGI_FORMAT_R11G11B10_FLOAT; } - inline static DXGI_FORMAT GetBackBufferFormat() { return DXGI_FORMAT_R10G10B10A2_UNORM; } - inline static DXGI_FORMAT GetDepthFormat() { return DXGI_FORMAT_D32_FLOAT; } - private: void Update(DX::StepTimer const& timer); @@ -102,9 +98,6 @@ private: std::unique_ptr m_keyboard; DirectX::Keyboard::KeyboardStateTracker m_keyboardButtons; std::unique_ptr m_mouse; -#else - // HDR Support - bool m_bIsTVInHDRMode; #endif // Render states diff --git a/Samples/Graphics/SimplePBR/StepTimer.h b/Samples/Graphics/SimplePBR/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/SimplePBR/StepTimer.h +++ b/Samples/Graphics/SimplePBR/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/SimplePBR/pch.h b/Samples/Graphics/SimplePBR/pch.h index 49a6c88..f4a3fa8 100644 --- a/Samples/Graphics/SimplePBR/pch.h +++ b/Samples/Graphics/SimplePBR/pch.h @@ -41,8 +41,8 @@ #include -#if _GRDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GRDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -91,6 +91,7 @@ // then add the NuGet package WinPixEventRuntime to the project. #include #endif + #include "CommonStates.h" #include "DDSTextureLoader.h" #include "DescriptorHeap.h" @@ -111,6 +112,7 @@ #include "SpriteFont.h" #include "VertexTypes.h" #include "WICTextureLoader.h" + #include namespace DX diff --git a/Samples/Graphics/SmokeSimulation/DeviceResources.cpp b/Samples/Graphics/SmokeSimulation/DeviceResources.cpp index d76fd63..fa67816 100644 --- a/Samples/Graphics/SmokeSimulation/DeviceResources.cpp +++ b/Samples/Graphics/SmokeSimulation/DeviceResources.cpp @@ -31,14 +31,13 @@ DeviceResources::DeviceResources( m_rtvDescriptorSize(0), m_screenViewport{}, m_scissorRect{}, - m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_backBufferFormat(backBufferFormat), m_depthBufferFormat(depthBufferFormat), m_backBufferCount(backBufferCount), m_window(nullptr), m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), m_outputSize{0, 0, 1920, 1080}, - m_options(flags), - m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) + m_options(flags) { if (backBufferCount < 2 || backBufferCount > MAX_BACK_BUFFER_COUNT) { @@ -55,12 +54,16 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } } // Configures the Direct3D device, and stores handles to it and the device context. +#ifdef _GAMING_XBOX_SCARLETT +void DeviceResources::CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags) +#else void DeviceResources::CreateDeviceResources() +#endif { // Create the DX12 API device object. D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; @@ -77,6 +80,17 @@ void DeviceResources::CreateDeviceResources() params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#ifdef _GAMING_XBOX_SCARLETT + params.CreateDeviceFlags = createDeviceFlags; + +#if (_GXDK_VER >= 0x585D070E /* GXDK Edition 221000 */) + if (m_options & c_AmplificationShaders) + { + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + } +#endif +#endif HRESULT hr = D3D12XboxCreateDevice( nullptr, @@ -107,7 +121,7 @@ void DeviceResources::CreateDeviceResources() // Create descriptor heaps for render target views and depth stencil views. D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; - rtvDescriptorHeapDesc.NumDescriptors = (m_options & c_EnableHDR) ? (m_backBufferCount * 2) : m_backBufferCount; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); @@ -152,31 +166,46 @@ void DeviceResources::CreateDeviceResources() m_fenceEvent.Attach(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!m_fenceEvent.IsValid()) { - throw std::exception("CreateEvent"); + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "CreateEventEx"); } - if (m_options & c_Enable4K_UHD) + if (m_options & (c_Enable4K_UHD | c_EnableQHD)) { switch (XSystemGetDeviceType()) { case XSystemDeviceType::XboxOne: case XSystemDeviceType::XboxOneS: - case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: - m_options &= ~c_Enable4K_UHD; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080)\n"); -#endif + m_options &= ~(c_Enable4K_UHD | c_EnableQHD); break; + case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: + m_options &= ~c_Enable4K_UHD; + if (m_options & c_EnableQHD) + { + m_outputSize = { 0, 0, 2560, 1440 }; + } + break; + + case XSystemDeviceType::XboxScarlettAnaconda /* Xbox Series X */: + case XSystemDeviceType::XboxOneXDevkit: + case XSystemDeviceType::XboxScarlettDevkit: default: - m_outputSize = { 0, 0, 3840, 2160 }; -#ifdef _DEBUG - OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160)\n"); -#endif + m_outputSize = (m_options & c_Enable4K_UHD) ? RECT{ 0, 0, 3840, 2160 } : RECT{ 0, 0, 2560, 1440 }; break; } } +#ifdef _DEBUG + const char* info = nullptr; + switch (m_outputSize.bottom) + { + case 2160: info = "INFO: Swapchain using 4k (3840 x 2160)\n"; break; + case 1440: info = "INFO: Swapchain using 1440p (2560 x 1440)\n"; break; + default: info = "INFO: Swapchain using 1080p (1920 x 1080)\n"; break; + } + OutputDebugStringA(info); +#endif + RegisterFrameEvents(); } @@ -185,7 +214,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { if (!m_window) { - throw std::exception("Call SetWindow with a valid window handle"); + throw std::logic_error("Call SetWindow with a valid Win32 window handle"); } // Wait until all previous GPU work is complete. @@ -198,7 +227,6 @@ void DeviceResources::CreateWindowSizeDependentResources() for (UINT n = 0; n < m_backBufferCount; n++) { m_renderTargets[n].Reset(); - m_renderTargetsGameDVR[n].Reset(); m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; } @@ -208,7 +236,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -219,6 +247,13 @@ void DeviceResources::CreateWindowSizeDependentResources() ); swapChainBufferDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; +#ifdef _GAMING_XBOX_XBOXONE + if (m_options & c_EnableHDR) + { + swapChainBufferDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_AUTOMATIC_GAMEDVR_TONE_MAP; + } +#endif + D3D12_CLEAR_VALUE swapChainOptimizedClearValue = {}; swapChainOptimizedClearValue.Format = m_backBufferFormat; @@ -240,41 +275,12 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); } - if (m_options & c_EnableHDR) - { - swapChainBufferDesc.Format = swapChainOptimizedClearValue.Format = m_gameDVRFormat; - - for (UINT n = 0; n < m_backBufferCount; n++) - { - ThrowIfFailed(m_d3dDevice->CreateCommittedResource( - &swapChainHeapProperties, - D3D12_HEAP_FLAG_ALLOW_DISPLAY, - &swapChainBufferDesc, - D3D12_RESOURCE_STATE_PRESENT, - &swapChainOptimizedClearValue, - IID_GRAPHICS_PPV_ARGS(m_renderTargetsGameDVR[n].GetAddressOf()))); - - wchar_t name[25] = {}; - swprintf_s(name, L"GameDVR Render target %u", n); - m_renderTargetsGameDVR[n]->SetName(name); - - D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; - rtvDesc.Format = m_gameDVRFormat; - rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + n), m_rtvDescriptorSize); - m_d3dDevice->CreateRenderTargetView(m_renderTargetsGameDVR[n].Get(), &rtvDesc, rtvDescriptorGameDVR); - } - } - // Reset the index to the current back buffer. m_backBufferIndex = 0; @@ -282,7 +288,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -295,7 +301,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -331,10 +337,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -342,23 +344,10 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), - beforeState, afterState), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), - beforeState, afterState); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, afterState); + m_commandList->ResourceBarrier(1, &barrier); } } @@ -368,20 +357,10 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - if (m_options & c_EnableHDR) - { - D3D12_RESOURCE_BARRIER barriers[2] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), - }; - m_commandList->ResourceBarrier(_countof(barriers), barriers); - } - else - { - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); - m_commandList->ResourceBarrier(1, &barrier); - } + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); } // Send the command list off to the GPU for processing. @@ -389,32 +368,24 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); // Present the backbuffer using the PresentX API. - D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters[2] = {}; - planeParameters[0].Token = planeParameters[1].Token = m_framePipelineToken; - planeParameters[0].ResourceCount = planeParameters[1].ResourceCount = 1; - planeParameters[0].ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); + D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters = {}; + planeParameters.Token = m_framePipelineToken; + planeParameters.ResourceCount = 1; + planeParameters.ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); if (m_options & c_EnableHDR) { - planeParameters[0].pSrcViewRects = planeParameters[1].pSrcViewRects = &m_outputSize; - planeParameters[0].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; - planeParameters[1].ppResources = m_renderTargetsGameDVR[m_backBufferIndex].GetAddressOf(); - planeParameters[1].ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; - - ThrowIfFailed( - m_commandQueue->PresentX(2, planeParameters, params) - ); - } - else - { - ThrowIfFailed( - m_commandQueue->PresentX(1, planeParameters, params) - ); + planeParameters.ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; } - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + ThrowIfFailed( + m_commandQueue->PresentX(1, &planeParameters, params) + ); - MoveToNextFrame(); + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -436,13 +407,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -451,25 +422,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/Graphics/SmokeSimulation/DeviceResources.h b/Samples/Graphics/SmokeSimulation/DeviceResources.h index 1d26b17..4924894 100644 --- a/Samples/Graphics/SmokeSimulation/DeviceResources.h +++ b/Samples/Graphics/SmokeSimulation/DeviceResources.h @@ -10,8 +10,11 @@ namespace DX class DeviceResources { public: - static constexpr unsigned int c_Enable4K_UHD = 0x1; - static constexpr unsigned int c_EnableHDR = 0x2; + static constexpr unsigned int c_Enable4K_UHD = 0x1; + static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_ReverseDepth = 0x8; + static constexpr unsigned int c_AmplificationShaders = 0x10; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -25,7 +28,11 @@ namespace DX DeviceResources(DeviceResources const&) = delete; DeviceResources& operator= (DeviceResources const&) = delete; +#ifdef _GAMING_XBOX_SCARLETT + void CreateDeviceResources(D3D12XBOX_CREATE_DEVICE_FLAGS createDeviceFlags = D3D12XBOX_CREATE_DEVICE_FLAG_NONE); +#else void CreateDeviceResources(); +#endif void CreateWindowSizeDependentResources(); void SetWindow(HWND window) noexcept { m_window = window; } void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT, @@ -35,6 +42,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -67,19 +75,7 @@ namespace DX return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); } - // Direct3D HDR Game DVR support for Xbox One. - ID3D12Resource* GetGameDVRRenderTarget() const noexcept { return m_renderTargetsGameDVR[m_backBufferIndex].Get(); } - DXGI_FORMAT GetGameDVRFormat() const noexcept { return m_gameDVRFormat; } - - CD3DX12_CPU_DESCRIPTOR_HANDLE GetGameDVRRenderTargetView() const noexcept - { - return CD3DX12_CPU_DESCRIPTOR_HANDLE( - m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(m_backBufferCount + m_backBufferIndex), m_rtvDescriptorSize); - } - private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; @@ -126,9 +122,5 @@ namespace DX // DeviceResources options (see flags above) unsigned int m_options; - - // Direct3D HDR Game DVR support for Xbox One. - Microsoft::WRL::ComPtr m_renderTargetsGameDVR[MAX_BACK_BUFFER_COUNT]; - DXGI_FORMAT m_gameDVRFormat; }; } diff --git a/Samples/Graphics/SmokeSimulation/Main.cpp b/Samples/Graphics/SmokeSimulation/Main.cpp index 1da6ae1..40f8e64 100644 --- a/Samples/Graphics/SmokeSimulation/Main.cpp +++ b/Samples/Graphics/SmokeSimulation/Main.cpp @@ -1,7 +1,7 @@ //-------------------------------------------------------------------------------------- // Main.cpp // -// Entry point for Microsoft GDK with Xbox extensions. +// Entry point for Microsoft GDK with Xbox extensions // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. @@ -18,16 +18,25 @@ using namespace DirectX; +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +#pragma warning(disable : 4061) + namespace { std::unique_ptr g_sample; HANDLE g_plmSuspendComplete = nullptr; HANDLE g_plmSignalResume = nullptr; -}; +} bool g_HDRMode = false; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void SetDisplayMode() noexcept; +void ExitSample() noexcept; // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) @@ -58,6 +67,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp // Register class and create window PAPPSTATE_REGISTRATION hPLM = {}; + PAPPCONSTRAIN_REGISTRATION hPLM2 = {}; + { // Register class WNDCLASSEXA wcex = {}; @@ -66,7 +77,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.lpszClassName = u8"SmokeSimulationWindowClass"; - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); if (!RegisterClassExA(&wcex)) return 1; @@ -79,17 +90,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp ShowWindow(hwnd, nCmdShow); - if (g_sample->RequestHDRMode()) - { - // Request HDR mode. - auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); - - g_HDRMode = (result == XDisplayHdrModeResult::Enabled); - - #ifdef _DEBUG - OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); - #endif - } + SetDisplayMode(); SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(g_sample.get())); @@ -116,7 +117,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp PostMessage(reinterpret_cast(context), WM_USER, 0, 0); // To defer suspend, you must wait to exit this callback - (void)WaitForSingleObject(g_plmSuspendComplete, INFINITE); + std::ignore = WaitForSingleObject(g_plmSuspendComplete, INFINITE); } else { @@ -124,6 +125,13 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp } }, hwnd, &hPLM)) return 1; + + if (RegisterAppConstrainedChangeNotification([](BOOLEAN constrained, PVOID context) + { + // To ensure we use the main UI thread to process the notification, we self-post a message + SendMessage(reinterpret_cast(context), WM_USER + 1, (constrained) ? 1u : 0u, 0); + }, hwnd, &hPLM2)) + return 1; } // Main message loop @@ -144,13 +152,14 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp g_sample.reset(); UnregisterAppStateChangeNotification(hPLM); - + UnregisterAppConstrainedChangeNotification(hPLM2); + CloseHandle(g_plmSuspendComplete); CloseHandle(g_plmSignalResume); XGameRuntimeUninitialize(); - return (int) msg.wParam; + return static_cast(msg.wParam); } // Windows procedure @@ -168,18 +177,52 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // Complete deferral SetEvent(g_plmSuspendComplete); - (void)WaitForSingleObject(g_plmSignalResume, INFINITE); + std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); + + SetDisplayMode(); sample->OnResuming(); } break; + + case WM_USER + 1: + if (sample) + { + if (wParam) + { + sample->OnConstrained(); + } + else + { + SetDisplayMode(); + + sample->OnUnConstrained(); + } + } + break; } return DefWindowProc(hWnd, message, wParam, lParam); } +// HDR helper +void SetDisplayMode() noexcept +{ + if (g_sample && g_sample->RequestHDRMode()) + { + // Request HDR mode. + auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); + + g_HDRMode = (result == XDisplayHdrModeResult::Enabled); + +#ifdef _DEBUG + OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); +#endif + } +} + // Exit helper -void ExitSample() +void ExitSample() noexcept { PostQuitMessage(0); } diff --git a/Samples/Graphics/SmokeSimulation/SmokeSimulation.cpp b/Samples/Graphics/SmokeSimulation/SmokeSimulation.cpp index 264f5b5..525adf8 100644 --- a/Samples/Graphics/SmokeSimulation/SmokeSimulation.cpp +++ b/Samples/Graphics/SmokeSimulation/SmokeSimulation.cpp @@ -8,7 +8,7 @@ #include "pch.h" #include "SmokeSimulation.h" -extern void ExitSample(); +extern void ExitSample() noexcept; using namespace DirectX; @@ -57,6 +57,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); @@ -184,16 +186,16 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); commandList->ClearRenderTargetView(rtvDescriptor, DirectX::Colors::Black, 0, nullptr); commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -226,8 +228,6 @@ void Sample::CreateDeviceDependentResources() m_commonStates = std::make_unique(device); m_srvPile = std::make_unique( device, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 128, SRV_Count); @@ -237,7 +237,7 @@ void Sample::CreateDeviceDependentResources() resourceUpload.Begin(); // HUD - auto backBufferRts = RenderTargetState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState backBufferRts(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); auto spritePSD = SpriteBatchPipelineStateDescription(backBufferRts, &CommonStates::AlphaBlend); m_hudBatch = std::make_unique(device, resourceUpload, spritePSD); @@ -249,7 +249,7 @@ void Sample::CreateDeviceDependentResources() void Sample::CreateWindowSizeDependentResources() { auto device = m_deviceResources->GetD3DDevice(); - auto size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); // Calculate display dimensions. m_displayWidth = size.right - size.left; diff --git a/Samples/Graphics/SmokeSimulation/SmokeSimulation.h b/Samples/Graphics/SmokeSimulation/SmokeSimulation.h index 33075ba..76bdaff 100644 --- a/Samples/Graphics/SmokeSimulation/SmokeSimulation.h +++ b/Samples/Graphics/SmokeSimulation/SmokeSimulation.h @@ -20,18 +20,26 @@ public: Sample() noexcept(false); ~Sample(); + Sample(Sample&&) = default; + Sample& operator= (Sample&&) = default; + + Sample(Sample const&) = delete; + Sample& operator= (Sample const&) = delete; + // Initialization and management void Initialize(HWND window); - // Basic Sample loop + // Basic render loop void Tick(); // Messages void OnSuspending(); void OnResuming(); + void OnConstrained() {} + void OnUnConstrained() {} // Properties - bool RequestHDRMode() const { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } + bool RequestHDRMode() const noexcept { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } private: void Update(const DX::StepTimer& timer); diff --git a/Samples/Graphics/SmokeSimulation/StepTimer.h b/Samples/Graphics/SmokeSimulation/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/SmokeSimulation/StepTimer.h +++ b/Samples/Graphics/SmokeSimulation/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/SmokeSimulation/pch.h b/Samples/Graphics/SmokeSimulation/pch.h index a6168ba..28dd6f8 100644 --- a/Samples/Graphics/SmokeSimulation/pch.h +++ b/Samples/Graphics/SmokeSimulation/pch.h @@ -37,8 +37,8 @@ #include -#if _GXDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GXDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT @@ -56,14 +56,21 @@ #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include +#include +#include +#include -#include -#include #include #include @@ -94,7 +101,7 @@ namespace DX class com_exception : public std::exception { public: - com_exception(HRESULT hr) : result(hr) {} + com_exception(HRESULT hr) noexcept : result(hr) {} const char* what() const override { diff --git a/Samples/Graphics/SmokeSimulation/readme.docx b/Samples/Graphics/SmokeSimulation/readme.docx index 2cee66b..3da31d2 100644 Binary files a/Samples/Graphics/SmokeSimulation/readme.docx and b/Samples/Graphics/SmokeSimulation/readme.docx differ diff --git a/Samples/Graphics/VisibilityBuffer/Source/DeviceResources.cpp b/Samples/Graphics/VisibilityBuffer/Source/DeviceResources.cpp index 2f493c9..1fd8035 100644 --- a/Samples/Graphics/VisibilityBuffer/Source/DeviceResources.cpp +++ b/Samples/Graphics/VisibilityBuffer/Source/DeviceResources.cpp @@ -10,7 +10,6 @@ using namespace DX; using Microsoft::WRL::ComPtr; -#ifdef _GAMING_DESKTOP #ifdef __clang__ #pragma clang diagnostic ignored "-Wcovered-switch-default" #pragma clang diagnostic ignored "-Wswitch-enum" @@ -18,6 +17,7 @@ using Microsoft::WRL::ComPtr; #pragma warning(disable : 4061) +#ifdef _GAMING_DESKTOP namespace { inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) noexcept @@ -70,7 +70,7 @@ DeviceResources::~DeviceResources() // Ensure we present a blank screen before cleaning up resources. if (m_commandQueue) { - (void)m_commandQueue->PresentX(0, nullptr, nullptr); + std::ignore = m_commandQueue->PresentX(0, nullptr, nullptr); } #endif } @@ -318,7 +318,7 @@ void DeviceResources::CreateWindowSizeDependentResources() // Obtain the back buffers for this window which will be the final render targets // and create render target views for each of them. - CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_backBufferFormat, @@ -350,7 +350,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -361,7 +361,7 @@ void DeviceResources::CreateWindowSizeDependentResources() #else // _GAMING_DESKTOP - DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + const DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); // If the swap chain already exists, resize it, otherwise create one. if (m_swapChain) @@ -444,7 +444,7 @@ void DeviceResources::CreateWindowSizeDependentResources() rtvDesc.Format = m_backBufferFormat; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( + const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(n), m_rtvDescriptorSize); m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); @@ -459,7 +459,7 @@ void DeviceResources::CreateWindowSizeDependentResources() { // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view // on this surface. - CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + const CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( m_depthBufferFormat, @@ -583,12 +583,6 @@ void DeviceResources::HandleDeviceLost() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { -#ifdef _GAMING_XBOX - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); -#endif - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -596,7 +590,8 @@ void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_ if (beforeState != afterState) { // Transition the render target into the correct state to allow for drawing into it. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), beforeState, afterState); m_commandList->ResourceBarrier(1, &barrier); } @@ -608,7 +603,9 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) if (beforeState != D3D12_RESOURCE_STATE_PRESENT) { // Transition the render target to the state that allows it to be presented to the display. - D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + const D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_renderTargets[m_backBufferIndex].Get(), + beforeState, D3D12_RESOURCE_STATE_PRESENT); m_commandList->ResourceBarrier(1, &barrier); } @@ -628,9 +625,12 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) m_commandQueue->PresentX(1, &planeParameters, nullptr) ); - // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. -#else + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + +#else // _GAMING_DESKTOP // The first argument instructs DXGI to block until VSync, putting the application // to sleep until the next VSync. This ensures we don't waste any cycles rendering @@ -653,9 +653,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) ThrowIfFailed(hr); } -#endif - MoveToNextFrame(); +#endif } // Handle GPU suspend/resume @@ -681,13 +680,13 @@ void DeviceResources::WaitForGpu() noexcept if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) { // Schedule a Signal command in the GPU queue. - UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) { // Wait until the Signal has been processed. if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) { - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); // Increment the fence value for the current frame. m_fenceValues[m_backBufferIndex]++; @@ -696,32 +695,20 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() -{ - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. #ifdef _GAMING_XBOX - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; -#else - m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); -#endif - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() +{ + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } -#ifdef _GAMING_XBOX // Set frame interval and register for frame events void DeviceResources::RegisterFrameEvents() { @@ -750,7 +737,30 @@ void DeviceResources::RegisterFrameEvents() nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE)); } -#else + +#else // _GAMING_DESKTOP + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + // This method acquires the first available hardware adapter that supports Direct3D 12. // If no such adapter can be found, try WARP. Otherwise throw an exception. void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) diff --git a/Samples/Graphics/VisibilityBuffer/Source/DeviceResources.h b/Samples/Graphics/VisibilityBuffer/Source/DeviceResources.h index 1cee56a..c6e321c 100644 --- a/Samples/Graphics/VisibilityBuffer/Source/DeviceResources.h +++ b/Samples/Graphics/VisibilityBuffer/Source/DeviceResources.h @@ -45,6 +45,9 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; +#ifdef _GAMING_XBOX + void WaitForOrigin(); +#endif // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -81,10 +84,10 @@ namespace DX } private: - void MoveToNextFrame(); #ifdef _GAMING_XBOX void RegisterFrameEvents(); #else + void MoveToNextFrame(); void GetAdapter(IDXGIAdapter1** ppAdapter); #endif diff --git a/Samples/Graphics/VisibilityBuffer/Source/Main.cpp b/Samples/Graphics/VisibilityBuffer/Source/Main.cpp index b7cb101..8a42508 100644 --- a/Samples/Graphics/VisibilityBuffer/Source/Main.cpp +++ b/Samples/Graphics/VisibilityBuffer/Source/Main.cpp @@ -117,12 +117,18 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp { case XSystemDeviceType::XboxOne: case XSystemDeviceType::XboxOneS: - case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: #ifdef _DEBUG OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080)\n"); #endif break; + case XSystemDeviceType::XboxScarlettLockhart /* Xbox Series S */: + rc = { 0, 0, 2560, 1440 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1440p (2560 x 1440)\n"); +#endif + break; + case XSystemDeviceType::XboxScarlettAnaconda /* Xbox Series X */: case XSystemDeviceType::XboxOneXDevkit: case XSystemDeviceType::XboxScarlettDevkit: @@ -408,7 +414,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); diff --git a/Samples/Graphics/VisibilityBuffer/Source/StepTimer.h b/Samples/Graphics/VisibilityBuffer/Source/StepTimer.h index bb15fff..2dbefcb 100644 --- a/Samples/Graphics/VisibilityBuffer/Source/StepTimer.h +++ b/Samples/Graphics/VisibilityBuffer/Source/StepTimer.h @@ -111,7 +111,7 @@ namespace DX timeDelta *= TicksPerSecond; timeDelta /= static_cast(m_qpcFrequency.QuadPart); - uint32_t lastFrameCount = m_frameCount; + const uint32_t lastFrameCount = m_frameCount; if (m_isFixedTimeStep) { diff --git a/Samples/Graphics/VisibilityBuffer/Source/VisibilityBuffer.cpp b/Samples/Graphics/VisibilityBuffer/Source/VisibilityBuffer.cpp index dedc932..a6b1573 100644 --- a/Samples/Graphics/VisibilityBuffer/Source/VisibilityBuffer.cpp +++ b/Samples/Graphics/VisibilityBuffer/Source/VisibilityBuffer.cpp @@ -112,6 +112,10 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); +#ifdef _GAMING_XBOX + m_deviceResources->WaitForOrigin(); +#endif + m_timer.Tick([&]() { Update(m_timer); @@ -128,7 +132,7 @@ void Sample::Update(DX::StepTimer const&) { float elapsed = static_cast(m_timer.GetElapsedSeconds()); -#ifdef _GAMING_XBOX +#ifdef USING_GAMEINPUT auto pad = m_gamePad->GetState(GamePad::c_MergedInput); #else auto pad = m_gamePad->GetState(0); @@ -226,7 +230,7 @@ void Sample::Render() m_gpuTimer->Start(commandList, 0); ID3D12DescriptorHeap* heaps[] = { m_resourceDescriptors->Heap(), m_samplerDescriptors->Heap() }; - commandList->SetDescriptorHeaps(_countof(heaps), heaps); + commandList->SetDescriptorHeaps(static_cast(std::size(heaps)), heaps); if (m_useVisibility) { @@ -276,8 +280,8 @@ void Sample::RenderVisibilityMode() commandList->SetPipelineState(m_visibilityVSPSO.Get()); } - auto rtvDescriptor = m_renderDescriptors->GetCpuHandle(RTDescriptors::VisibilityRTV); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_renderDescriptors->GetCpuHandle(RTDescriptors::VisibilityRTV); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->ClearRenderTargetView(rtvDescriptor, Colors::Black, 0, nullptr); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); @@ -344,7 +348,7 @@ void Sample::RenderVisibilityMode() // Run fullscreen reconstruction pass in compute. // Performs position and uv reconstruction, then runs pixel shader logic per screen pixel. { - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, nullptr); @@ -460,7 +464,7 @@ void Sample::RenderForwardMode() void Sample::RenderHUD() { auto commandList = m_deviceResources->GetCommandList(); - auto size = m_deviceResources->GetOutputSize(); + auto const size = m_deviceResources->GetOutputSize(); D3D12_VIEWPORT viewport = { 0, 0, float(size.right), float(size.bottom), 0, 1 }; auto& font = ((size.right - size.left) > 1920) ? m_bigFont : m_smallFont; @@ -529,8 +533,8 @@ void Sample::Clear() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); // Clear the views. - auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); - auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + auto const rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); @@ -540,8 +544,8 @@ void Sample::Clear() commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. - auto viewport = m_deviceResources->GetScreenViewport(); - auto scissorRect = m_deviceResources->GetScissorRect(); + auto const viewport = m_deviceResources->GetScreenViewport(); + auto const scissorRect = m_deviceResources->GetScissorRect(); commandList->RSSetViewports(1, &viewport); commandList->RSSetScissorRects(1, &scissorRect); @@ -551,14 +555,6 @@ void Sample::Clear() #pragma region Message Handlers // Message handlers -void Sample::OnActivated() -{ -} - -void Sample::OnDeactivated() -{ -} - void Sample::OnSuspending() { m_deviceResources->Suspend(); @@ -671,7 +667,7 @@ void Sample::LoadModels() // Load sdkmesh models. OutputDebugStringA("Loading model...\n"); -#if _GAMING_DESKTOP +#ifdef _GAMING_DESKTOP const wchar_t* dragonPath = L"ATGDragonPosedWithBakedDiffuse\\Dragon_LOD1_993KTri.sdkmes_"; const wchar_t* cityPath = L"AliasSampleCityBlock\\CityBlockConcrete.sdkmesh"; #else @@ -838,8 +834,8 @@ void Sample::BuildPSOs() { auto device = m_deviceResources->GetD3DDevice(); - RenderTargetState rtStateUI(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); - RenderTargetState rtStateVisibilityBuffer(DXGI_FORMAT_R32_UINT, m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState rtStateUI(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState rtStateVisibilityBuffer(DXGI_FORMAT_R32_UINT, m_deviceResources->GetDepthBufferFormat()); // Setup PSO for Visibility Buffer Rasterization. { @@ -1043,7 +1039,7 @@ void Sample::BuildObjectBuffer() void Sample::LoadTextures() { -#if _GAMING_DESKTOP +#ifdef _GAMING_DESKTOP const wchar_t* dragonTexture = L"ATGDragonPosedWithBakedDiffuse\\Dragon_diffuse.DD_"; const wchar_t* cityTexture = L"AliasSampleCityBlock\\Concrete.DDS"; #else @@ -1067,7 +1063,7 @@ void Sample::BuildHUDObjects() resourceUpload.Begin(); - RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + const RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); SpriteBatchPipelineStateDescription pd(rtState); m_spriteBatch = std::make_unique(device, resourceUpload, pd); @@ -1196,7 +1192,7 @@ void Sample::LoadTexture(const wchar_t* path, ComPtr& texture, u auto subresourceSize = static_cast(subresources.size()); const auto uploadBufferSize = GetRequiredIntermediateSize(texture.Get(), 0, subresourceSize); - auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + auto const heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); auto bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize); // create upload heap to transfer texture data to resource. @@ -1244,9 +1240,9 @@ void Sample::LoadTexture(const wchar_t* path, ComPtr& texture, u void Sample::CreateWindowSizeDependentResources() { auto device = m_deviceResources->GetD3DDevice(); - auto size = m_deviceResources->GetOutputSize(); - auto width = static_cast(size.right); - auto height = static_cast(size.bottom); + auto const size = m_deviceResources->GetOutputSize(); + auto const width = static_cast(size.right); + auto const height = static_cast(size.bottom); m_visibilityBuffer->SetWindow(size); m_help->SetWindow(size); diff --git a/Samples/Graphics/VisibilityBuffer/Source/VisibilityBuffer.h b/Samples/Graphics/VisibilityBuffer/Source/VisibilityBuffer.h index 2ece721..df68bf5 100644 --- a/Samples/Graphics/VisibilityBuffer/Source/VisibilityBuffer.h +++ b/Samples/Graphics/VisibilityBuffer/Source/VisibilityBuffer.h @@ -59,8 +59,8 @@ public: void OnDeviceRestored() override; // Messages - void OnActivated(); - void OnDeactivated(); + void OnActivated() {} + void OnDeactivated() {} void OnSuspending(); void OnResuming(); void OnWindowMoved(); diff --git a/Samples/Graphics/VisibilityBuffer/VisibilityBuffer/Readme.docx b/Samples/Graphics/VisibilityBuffer/VisibilityBuffer/Readme.docx index ece2f8e..fae40c2 100644 Binary files a/Samples/Graphics/VisibilityBuffer/VisibilityBuffer/Readme.docx and b/Samples/Graphics/VisibilityBuffer/VisibilityBuffer/Readme.docx differ diff --git a/Samples/Graphics/VisibilityBuffer/VisibilityBuffer/pch.h b/Samples/Graphics/VisibilityBuffer/VisibilityBuffer/pch.h index e546592..bed7426 100644 --- a/Samples/Graphics/VisibilityBuffer/VisibilityBuffer/pch.h +++ b/Samples/Graphics/VisibilityBuffer/VisibilityBuffer/pch.h @@ -41,9 +41,9 @@ #include -#if _GRDK_VER < 0x4A6117BE /* GDK Edition 210400 */ -#error This sample requires the April 2021 GDK or later -#endif +#if _GRDK_VER < 0x55F007B0 /* GDK Edition 211000 */ +#error This sample requires the October 2021 GDK or later +#endif #ifdef _GAMING_XBOX_SCARLETT #include diff --git a/Samples/IntroGraphics/SimpleBezier/DeviceResources.cpp b/Samples/IntroGraphics/SimpleBezier/DeviceResources.cpp index 4a73b52..a35a0db 100644 --- a/Samples/IntroGraphics/SimpleBezier/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleBezier/DeviceResources.cpp @@ -279,7 +279,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -315,10 +315,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -361,7 +357,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -398,25 +395,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/IntroGraphics/SimpleBezier/DeviceResources.h b/Samples/IntroGraphics/SimpleBezier/DeviceResources.h index 1f9a3a5..082b073 100644 --- a/Samples/IntroGraphics/SimpleBezier/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleBezier/DeviceResources.h @@ -12,6 +12,7 @@ namespace DX public: static constexpr unsigned int c_Enable4K_UHD = 0x1; static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_ReverseDepth = 0x8; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -35,6 +36,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -68,7 +70,6 @@ namespace DX } private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; diff --git a/Samples/IntroGraphics/SimpleBezier/SimpleBezier.cpp b/Samples/IntroGraphics/SimpleBezier/SimpleBezier.cpp index 418e74a..14fb441 100644 --- a/Samples/IntroGraphics/SimpleBezier/SimpleBezier.cpp +++ b/Samples/IntroGraphics/SimpleBezier/SimpleBezier.cpp @@ -168,6 +168,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); @@ -347,8 +349,10 @@ void Sample::Clear() auto const dsvDescriptor = m_deviceResources->GetDepthStencilView(); commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + // Use linear clear color for gamma-correct rendering. commandList->ClearRenderTargetView(rtvDescriptor, ATG::ColorsLinear::Background, 0, nullptr); + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Set the viewport and scissor rect. diff --git a/Samples/IntroGraphics/SimpleCompute/DeviceResources.cpp b/Samples/IntroGraphics/SimpleCompute/DeviceResources.cpp index 4a73b52..a35a0db 100644 --- a/Samples/IntroGraphics/SimpleCompute/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleCompute/DeviceResources.cpp @@ -279,7 +279,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -315,10 +315,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -361,7 +357,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -398,25 +395,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/IntroGraphics/SimpleCompute/DeviceResources.h b/Samples/IntroGraphics/SimpleCompute/DeviceResources.h index 1f9a3a5..082b073 100644 --- a/Samples/IntroGraphics/SimpleCompute/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleCompute/DeviceResources.h @@ -12,6 +12,7 @@ namespace DX public: static constexpr unsigned int c_Enable4K_UHD = 0x1; static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_ReverseDepth = 0x8; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -35,6 +36,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -68,7 +70,6 @@ namespace DX } private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; diff --git a/Samples/IntroGraphics/SimpleCompute/SimpleCompute.cpp b/Samples/IntroGraphics/SimpleCompute/SimpleCompute.cpp index 7313a60..93aa52b 100644 --- a/Samples/IntroGraphics/SimpleCompute/SimpleCompute.cpp +++ b/Samples/IntroGraphics/SimpleCompute/SimpleCompute.cpp @@ -136,6 +136,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); diff --git a/Samples/IntroGraphics/SimpleDeviceAndSwapChain/Readme.docx b/Samples/IntroGraphics/SimpleDeviceAndSwapChain/Readme.docx index b1dacfb..09b7fa0 100644 Binary files a/Samples/IntroGraphics/SimpleDeviceAndSwapChain/Readme.docx and b/Samples/IntroGraphics/SimpleDeviceAndSwapChain/Readme.docx differ diff --git a/Samples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.cpp b/Samples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.cpp index 9f73663..17000a5 100644 --- a/Samples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.cpp +++ b/Samples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.cpp @@ -1,7 +1,8 @@ //-------------------------------------------------------------------------------------- // SimpleDeviceAndSwapChain.cpp // -// Setting up a Direct3D 12.X device and swapchain for Microsoft GDK on Xbox +// Setting up a Direct3D 12.X device and swapchain for Microsoft GDK on Xbox using the +// PresentX API. // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. @@ -19,6 +20,7 @@ using namespace DirectX; using Microsoft::WRL::ComPtr; #define ENABLE_4K +#define ENABLE_AS #ifdef __clang__ #pragma clang diagnostic ignored "-Wcovered-switch-default" @@ -30,6 +32,9 @@ namespace { constexpr DXGI_FORMAT c_backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; constexpr DXGI_FORMAT c_depthBufferFormat = DXGI_FORMAT_D32_FLOAT; + + // For a "reverse" depth buffer use 0.0f instead of 1.0f for the depth clear value. + constexpr float c_depthClearValue = 1.0f; } Sample::Sample() noexcept : @@ -75,6 +80,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); @@ -142,10 +149,6 @@ void Sample::Render() // Helper method to clear the back buffers. void Sample::Clear() { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - DX::ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. DX::ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); DX::ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -162,10 +165,11 @@ void Sample::Clear() const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor( m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), static_cast(m_backBufferIndex), m_rtvDescriptorSize); + CD3DX12_CPU_DESCRIPTOR_HANDLE dsvDescriptor(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); m_commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); m_commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); - m_commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + m_commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, c_depthClearValue, 0, 0, nullptr); // Set the viewport and scissor rect. const D3D12_VIEWPORT viewport = { 0.0f, 0.0f, static_cast(m_outputWidth), static_cast(m_outputHeight), D3D12_MIN_DEPTH, D3D12_MAX_DEPTH }; @@ -205,7 +209,8 @@ void Sample::Present() // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % c_swapBufferCount; PIXEndEvent(); } @@ -255,6 +260,21 @@ void Sample::CreateDevice() params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#ifdef _GAMING_XBOX_SCARLETT + +#if (_GXDK_VER >= 0x4A6110CC /* GDK Edition 201100 */) + // Additional creation parameters for Xbox Series X|S. + params.CreateDeviceFlags = D3D12XBOX_CREATE_DEVICE_FLAG_NONE; +#endif + +#if defined(ENABLE_AS) && (_GXDK_VER >= 0x585D070E /* GDK Edition 221000 */) + // Use of Amplification Shaders (AS) requires explicit enabling on Xbox Series X|S + // as of the October 2022 GDK. + params.AmplificationShaderIndirectArgsBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.AmplificationShaderPayloadBufferSize = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); +#endif +#endif + HRESULT hr = D3D12XboxCreateDevice( nullptr, ¶ms, @@ -432,7 +452,7 @@ void Sample::CreateResources() ); depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; - CD3DX12_CLEAR_VALUE depthOptimizedClearValue(c_depthBufferFormat, 1.0f, 0); + CD3DX12_CLEAR_VALUE depthOptimizedClearValue(c_depthBufferFormat, c_depthClearValue, 0); DX::ThrowIfFailed(m_d3dDevice->CreateCommittedResource( &depthHeapProperties, @@ -483,37 +503,38 @@ void Sample::CreateResources() uploadResourcesFinished.wait(); } -void Sample::WaitForGpu() +void Sample::WaitForGpu() noexcept { - // Schedule a Signal command in the GPU queue. - DX::ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), m_fenceValues[m_backBufferIndex])); + // Since we call this method from the destructor, we want to make sure it doesn't throw C++ exceptions. + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + const UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - // Wait until the Signal has been processed. - DX::ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - - // Increment the fence value for the current frame. - m_fenceValues[m_backBufferIndex]++; + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } } -void Sample::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void Sample::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - DX::ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % c_swapBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - DX::ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled. + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + DX::ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } void Sample::RegisterFrameEvents() diff --git a/Samples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.h b/Samples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.h index 2e873ee..abdb236 100644 --- a/Samples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.h +++ b/Samples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.h @@ -48,8 +48,8 @@ private: void CreateDevice(); void CreateResources(); - void WaitForGpu(); - void MoveToNextFrame(); + void WaitForGpu() noexcept; + void WaitForOrigin(); void RegisterFrameEvents(); // Application state diff --git a/Samples/IntroGraphics/SimpleDeviceAndSwapChain/pch.h b/Samples/IntroGraphics/SimpleDeviceAndSwapChain/pch.h index 0f52700..5577810 100644 --- a/Samples/IntroGraphics/SimpleDeviceAndSwapChain/pch.h +++ b/Samples/IntroGraphics/SimpleDeviceAndSwapChain/pch.h @@ -35,9 +35,9 @@ #include #include -#include +#include -#if _GRDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ +#if _GXDK_VER < 0x4A610D2B /* GDK Edition 200600 */ #error This sample requires the June 2020 GDK or later #endif @@ -91,7 +91,7 @@ namespace DX class com_exception : public std::exception { public: - com_exception(HRESULT hr) : result(hr) {} + com_exception(HRESULT hr) noexcept : result(hr) {} const char* what() const override { diff --git a/Samples/IntroGraphics/SimpleDynamicResources/DeviceResources.cpp b/Samples/IntroGraphics/SimpleDynamicResources/DeviceResources.cpp index 3125701..1fd8035 100644 --- a/Samples/IntroGraphics/SimpleDynamicResources/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleDynamicResources/DeviceResources.cpp @@ -10,7 +10,6 @@ using namespace DX; using Microsoft::WRL::ComPtr; -#ifdef _GAMING_DESKTOP #ifdef __clang__ #pragma clang diagnostic ignored "-Wcovered-switch-default" #pragma clang diagnostic ignored "-Wswitch-enum" @@ -18,6 +17,7 @@ using Microsoft::WRL::ComPtr; #pragma warning(disable : 4061) +#ifdef _GAMING_DESKTOP namespace { inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) noexcept @@ -583,12 +583,6 @@ void DeviceResources::HandleDeviceLost() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { -#ifdef _GAMING_XBOX - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); -#endif - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -633,7 +627,10 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. -#else + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + +#else // _GAMING_DESKTOP // The first argument instructs DXGI to block until VSync, putting the application // to sleep until the next VSync. This ensures we don't waste any cycles rendering @@ -656,9 +653,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) ThrowIfFailed(hr); } -#endif - MoveToNextFrame(); +#endif } // Handle GPU suspend/resume @@ -699,32 +695,20 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() -{ - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. #ifdef _GAMING_XBOX - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; -#else - m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); -#endif - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() +{ + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } -#ifdef _GAMING_XBOX // Set frame interval and register for frame events void DeviceResources::RegisterFrameEvents() { @@ -753,7 +737,30 @@ void DeviceResources::RegisterFrameEvents() nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE)); } -#else + +#else // _GAMING_DESKTOP + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + // This method acquires the first available hardware adapter that supports Direct3D 12. // If no such adapter can be found, try WARP. Otherwise throw an exception. void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) diff --git a/Samples/IntroGraphics/SimpleDynamicResources/DeviceResources.h b/Samples/IntroGraphics/SimpleDynamicResources/DeviceResources.h index 8937789..ee6f56b 100644 --- a/Samples/IntroGraphics/SimpleDynamicResources/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleDynamicResources/DeviceResources.h @@ -43,6 +43,9 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; +#ifdef _GAMING_XBOX + void WaitForOrigin(); +#endif // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -79,10 +82,10 @@ namespace DX } private: - void MoveToNextFrame(); #ifdef _GAMING_XBOX void RegisterFrameEvents(); #else + void MoveToNextFrame(); void GetAdapter(IDXGIAdapter1** ppAdapter); #endif diff --git a/Samples/IntroGraphics/SimpleDynamicResources/Main.cpp b/Samples/IntroGraphics/SimpleDynamicResources/Main.cpp index 305ff30..bfe3c36 100644 --- a/Samples/IntroGraphics/SimpleDynamicResources/Main.cpp +++ b/Samples/IntroGraphics/SimpleDynamicResources/Main.cpp @@ -423,7 +423,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); diff --git a/Samples/IntroGraphics/SimpleDynamicResources/SimpleDynamicResources.cpp b/Samples/IntroGraphics/SimpleDynamicResources/SimpleDynamicResources.cpp index f665952..20d58e5 100644 --- a/Samples/IntroGraphics/SimpleDynamicResources/SimpleDynamicResources.cpp +++ b/Samples/IntroGraphics/SimpleDynamicResources/SimpleDynamicResources.cpp @@ -105,6 +105,10 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); +#ifdef _GAMING_XBOX + m_deviceResources->WaitForOrigin(); +#endif + m_timer.Tick([&]() { Update(m_timer); @@ -202,14 +206,6 @@ void Sample::Clear() #pragma region Message Handlers // Message handlers -void Sample::OnActivated() -{ -} - -void Sample::OnDeactivated() -{ -} - void Sample::OnSuspending() { m_deviceResources->Suspend(); diff --git a/Samples/IntroGraphics/SimpleDynamicResources/SimpleDynamicResources.h b/Samples/IntroGraphics/SimpleDynamicResources/SimpleDynamicResources.h index 8e5187a..745cf70 100644 --- a/Samples/IntroGraphics/SimpleDynamicResources/SimpleDynamicResources.h +++ b/Samples/IntroGraphics/SimpleDynamicResources/SimpleDynamicResources.h @@ -37,8 +37,8 @@ public: void OnDeviceRestored() override; // Messages - void OnActivated(); - void OnDeactivated(); + void OnActivated() {} + void OnDeactivated() {} void OnSuspending(); void OnResuming(); void OnWindowMoved(); diff --git a/Samples/IntroGraphics/SimpleInstancing/DeviceResources.cpp b/Samples/IntroGraphics/SimpleInstancing/DeviceResources.cpp index 4a73b52..a35a0db 100644 --- a/Samples/IntroGraphics/SimpleInstancing/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleInstancing/DeviceResources.cpp @@ -279,7 +279,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -315,10 +315,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -361,7 +357,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -398,25 +395,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/IntroGraphics/SimpleInstancing/DeviceResources.h b/Samples/IntroGraphics/SimpleInstancing/DeviceResources.h index 1f9a3a5..082b073 100644 --- a/Samples/IntroGraphics/SimpleInstancing/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleInstancing/DeviceResources.h @@ -12,6 +12,7 @@ namespace DX public: static constexpr unsigned int c_Enable4K_UHD = 0x1; static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_ReverseDepth = 0x8; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -35,6 +36,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -68,7 +70,6 @@ namespace DX } private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; diff --git a/Samples/IntroGraphics/SimpleInstancing/SimpleInstancing.cpp b/Samples/IntroGraphics/SimpleInstancing/SimpleInstancing.cpp index 1c2f67e..a66ea2a 100644 --- a/Samples/IntroGraphics/SimpleInstancing/SimpleInstancing.cpp +++ b/Samples/IntroGraphics/SimpleInstancing/SimpleInstancing.cpp @@ -88,6 +88,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); diff --git a/Samples/IntroGraphics/SimpleLighting/DeviceResources.cpp b/Samples/IntroGraphics/SimpleLighting/DeviceResources.cpp index 4a73b52..a35a0db 100644 --- a/Samples/IntroGraphics/SimpleLighting/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleLighting/DeviceResources.cpp @@ -279,7 +279,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -315,10 +315,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -361,7 +357,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -398,25 +395,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/IntroGraphics/SimpleLighting/DeviceResources.h b/Samples/IntroGraphics/SimpleLighting/DeviceResources.h index 1f9a3a5..082b073 100644 --- a/Samples/IntroGraphics/SimpleLighting/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleLighting/DeviceResources.h @@ -12,6 +12,7 @@ namespace DX public: static constexpr unsigned int c_Enable4K_UHD = 0x1; static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_ReverseDepth = 0x8; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -35,6 +36,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -68,7 +70,6 @@ namespace DX } private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; diff --git a/Samples/IntroGraphics/SimpleLighting/SimpleLighting.cpp b/Samples/IntroGraphics/SimpleLighting/SimpleLighting.cpp index 8d85954..8813ecd 100644 --- a/Samples/IntroGraphics/SimpleLighting/SimpleLighting.cpp +++ b/Samples/IntroGraphics/SimpleLighting/SimpleLighting.cpp @@ -71,6 +71,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); diff --git a/Samples/IntroGraphics/SimpleMSAA/DeviceResources.cpp b/Samples/IntroGraphics/SimpleMSAA/DeviceResources.cpp index 4a73b52..a35a0db 100644 --- a/Samples/IntroGraphics/SimpleMSAA/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleMSAA/DeviceResources.cpp @@ -279,7 +279,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -315,10 +315,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -361,7 +357,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -398,25 +395,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/IntroGraphics/SimpleMSAA/DeviceResources.h b/Samples/IntroGraphics/SimpleMSAA/DeviceResources.h index 1f9a3a5..082b073 100644 --- a/Samples/IntroGraphics/SimpleMSAA/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleMSAA/DeviceResources.h @@ -12,6 +12,7 @@ namespace DX public: static constexpr unsigned int c_Enable4K_UHD = 0x1; static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_ReverseDepth = 0x8; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -35,6 +36,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -68,7 +70,6 @@ namespace DX } private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; diff --git a/Samples/IntroGraphics/SimpleMSAA/SimpleMSAA.cpp b/Samples/IntroGraphics/SimpleMSAA/SimpleMSAA.cpp index dd0da9a..d27712a 100644 --- a/Samples/IntroGraphics/SimpleMSAA/SimpleMSAA.cpp +++ b/Samples/IntroGraphics/SimpleMSAA/SimpleMSAA.cpp @@ -81,6 +81,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); diff --git a/Samples/IntroGraphics/SimpleMeshShader/DeviceResources.cpp b/Samples/IntroGraphics/SimpleMeshShader/DeviceResources.cpp index dc09d60..1ad3919 100644 --- a/Samples/IntroGraphics/SimpleMeshShader/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleMeshShader/DeviceResources.cpp @@ -12,7 +12,6 @@ using namespace DX; using Microsoft::WRL::ComPtr; -#ifdef _GAMING_DESKTOP #ifdef __clang__ #pragma clang diagnostic ignored "-Wcovered-switch-default" #pragma clang diagnostic ignored "-Wswitch-enum" @@ -20,6 +19,7 @@ using Microsoft::WRL::ComPtr; #pragma warning(disable : 4061) +#ifdef _GAMING_DESKTOP namespace { inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) noexcept @@ -591,12 +591,6 @@ void DeviceResources::HandleDeviceLost() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { -#ifdef _GAMING_XBOX - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); -#endif - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -641,7 +635,10 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. -#else + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + +#else // _GAMING_DESKTOP // The first argument instructs DXGI to block until VSync, putting the application // to sleep until the next VSync. This ensures we don't waste any cycles rendering @@ -664,9 +661,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) ThrowIfFailed(hr); } -#endif - MoveToNextFrame(); +#endif } // Handle GPU suspend/resume @@ -707,32 +703,20 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() -{ - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. #ifdef _GAMING_XBOX - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; -#else - m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); -#endif - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() +{ + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } -#ifdef _GAMING_XBOX // Set frame interval and register for frame events void DeviceResources::RegisterFrameEvents() { @@ -761,7 +745,30 @@ void DeviceResources::RegisterFrameEvents() nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE)); } -#else + +#else // _GAMING_DESKTOP + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + // This method acquires the first available hardware adapter that supports Direct3D 12. // If no such adapter can be found, try WARP. Otherwise throw an exception. void DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) diff --git a/Samples/IntroGraphics/SimpleMeshShader/DeviceResources.h b/Samples/IntroGraphics/SimpleMeshShader/DeviceResources.h index 6fa15f5..22d1e6d 100644 --- a/Samples/IntroGraphics/SimpleMeshShader/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleMeshShader/DeviceResources.h @@ -46,6 +46,9 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; +#ifdef _GAMING_XBOX + void WaitForOrigin(); +#endif // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -82,10 +85,10 @@ namespace DX } private: - void MoveToNextFrame(); #ifdef _GAMING_XBOX void RegisterFrameEvents(); #else + void MoveToNextFrame(); void GetAdapter(IDXGIAdapter1** ppAdapter); #endif diff --git a/Samples/IntroGraphics/SimpleMeshShader/Main.cpp b/Samples/IntroGraphics/SimpleMeshShader/Main.cpp index 73dee7e..14e6160 100644 --- a/Samples/IntroGraphics/SimpleMeshShader/Main.cpp +++ b/Samples/IntroGraphics/SimpleMeshShader/Main.cpp @@ -369,7 +369,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); diff --git a/Samples/IntroGraphics/SimpleMeshShader/SimpleMeshShader.cpp b/Samples/IntroGraphics/SimpleMeshShader/SimpleMeshShader.cpp index 708bc6c..194e6a8 100644 --- a/Samples/IntroGraphics/SimpleMeshShader/SimpleMeshShader.cpp +++ b/Samples/IntroGraphics/SimpleMeshShader/SimpleMeshShader.cpp @@ -74,6 +74,10 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); +#ifdef _GAMING_XBOX + m_deviceResources->WaitForOrigin(); +#endif + m_timer.Tick([&]() { Update(m_timer); @@ -200,14 +204,6 @@ void Sample::DrawHUD(ID3D12GraphicsCommandList* commandList) #pragma region Message Handlers // Message handlers -void Sample::OnActivated() -{ -} - -void Sample::OnDeactivated() -{ -} - void Sample::OnSuspending() { m_deviceResources->Suspend(); diff --git a/Samples/IntroGraphics/SimpleMeshShader/SimpleMeshShader.h b/Samples/IntroGraphics/SimpleMeshShader/SimpleMeshShader.h index ff847d5..b964068 100644 --- a/Samples/IntroGraphics/SimpleMeshShader/SimpleMeshShader.h +++ b/Samples/IntroGraphics/SimpleMeshShader/SimpleMeshShader.h @@ -37,8 +37,8 @@ public: void OnDeviceRestored() override; // Messages - void OnActivated(); - void OnDeactivated(); + void OnActivated() {} + void OnDeactivated() {} void OnSuspending(); void OnResuming(); void OnWindowMoved(); diff --git a/Samples/IntroGraphics/SimpleSamplerFeedback/DeviceResources.cpp b/Samples/IntroGraphics/SimpleSamplerFeedback/DeviceResources.cpp index 4a73b52..004dd17 100644 --- a/Samples/IntroGraphics/SimpleSamplerFeedback/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleSamplerFeedback/DeviceResources.cpp @@ -1,6 +1,8 @@ // // DeviceResources.cpp - A wrapper for the Direct3D 12.X device and swapchain // +// Modified to use require Xbox Series X|S +// #include "pch.h" #include "DeviceResources.h" @@ -279,7 +281,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -315,10 +317,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -355,13 +353,19 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const planeParameters.ResourceCount = 1; planeParameters.ppResources = m_renderTargets[m_backBufferIndex].GetAddressOf(); + if (m_options & c_EnableHDR) + { + planeParameters.ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; + } + ThrowIfFailed( m_commandQueue->PresentX(1, &planeParameters, params) ); // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -398,25 +402,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/IntroGraphics/SimpleSamplerFeedback/DeviceResources.h b/Samples/IntroGraphics/SimpleSamplerFeedback/DeviceResources.h index bad1254..9c68059 100644 --- a/Samples/IntroGraphics/SimpleSamplerFeedback/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleSamplerFeedback/DeviceResources.h @@ -1,7 +1,7 @@ // // DeviceResources.h - A wrapper for the Direct3D 12.X device and swapchain // -// Modified to use ID3D12Device8/ID3D12GraphicsCommandList5 +// Modified to use require Xbox Series X|S // #pragma once @@ -14,6 +14,8 @@ namespace DX public: static constexpr unsigned int c_Enable4K_UHD = 0x1; static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_EnableHDR = 0x4; + static constexpr unsigned int c_ReverseDepth = 0x8; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -37,6 +39,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -70,7 +73,6 @@ namespace DX } private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; diff --git a/Samples/IntroGraphics/SimpleSamplerFeedback/Main.cpp b/Samples/IntroGraphics/SimpleSamplerFeedback/Main.cpp index fbd1377..24bbb81 100644 --- a/Samples/IntroGraphics/SimpleSamplerFeedback/Main.cpp +++ b/Samples/IntroGraphics/SimpleSamplerFeedback/Main.cpp @@ -13,6 +13,7 @@ #include "ATGTelemetry.h" #include +#include #include using namespace DirectX; @@ -31,7 +32,10 @@ namespace HANDLE g_plmSignalResume = nullptr; } +bool g_HDRMode = false; + LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void SetDisplayMode() noexcept; void ExitSample() noexcept; // Entry point @@ -86,6 +90,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp ShowWindow(hwnd, nCmdShow); + SetDisplayMode(); + SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(g_sample.get())); // Sample Usage Telemetry @@ -173,6 +179,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) std::ignore = WaitForSingleObject(g_plmSignalResume, INFINITE); + SetDisplayMode(); + sample->OnResuming(); } break; @@ -186,6 +194,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { + SetDisplayMode(); + sample->OnUnConstrained(); } } @@ -195,6 +205,22 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) return DefWindowProc(hWnd, message, wParam, lParam); } +// HDR helper +void SetDisplayMode() noexcept +{ + if (g_sample && g_sample->RequestHDRMode()) + { + // Request HDR mode. + auto result = XDisplayTryEnableHdrMode(XDisplayHdrModePreference::PreferHdr, nullptr); + + g_HDRMode = (result == XDisplayHdrModeResult::Enabled); + +#ifdef _DEBUG + OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); +#endif + } +} + // Exit helper void ExitSample() noexcept { diff --git a/Samples/IntroGraphics/SimpleSamplerFeedback/SimpleSamplerFeedback.cpp b/Samples/IntroGraphics/SimpleSamplerFeedback/SimpleSamplerFeedback.cpp index 5dfdbb9..d720ed1 100644 --- a/Samples/IntroGraphics/SimpleSamplerFeedback/SimpleSamplerFeedback.cpp +++ b/Samples/IntroGraphics/SimpleSamplerFeedback/SimpleSamplerFeedback.cpp @@ -69,6 +69,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame++); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); diff --git a/Samples/IntroGraphics/SimpleSamplerFeedback/SimpleSamplerFeedback.h b/Samples/IntroGraphics/SimpleSamplerFeedback/SimpleSamplerFeedback.h index 3e2b38c..a146f19 100644 --- a/Samples/IntroGraphics/SimpleSamplerFeedback/SimpleSamplerFeedback.h +++ b/Samples/IntroGraphics/SimpleSamplerFeedback/SimpleSamplerFeedback.h @@ -85,6 +85,9 @@ public: void OnConstrained() {} void OnUnConstrained() {} + // Properties + bool RequestHDRMode() const noexcept { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } + private: void Update(DX::StepTimer const& timer); diff --git a/Samples/IntroGraphics/SimpleSamplerFeedback/pch.h b/Samples/IntroGraphics/SimpleSamplerFeedback/pch.h index 50093a5..1290adf 100644 --- a/Samples/IntroGraphics/SimpleSamplerFeedback/pch.h +++ b/Samples/IntroGraphics/SimpleSamplerFeedback/pch.h @@ -37,7 +37,7 @@ #include -#if _GXDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ +#if _GXDK_VER < 0x4A610D2B /* GDK Edition 200600 */ #error This sample requires the June 2020 GDK or later #endif @@ -67,6 +67,7 @@ #include #include #include +#include #include diff --git a/Samples/IntroGraphics/SimpleTexture/DeviceResources.cpp b/Samples/IntroGraphics/SimpleTexture/DeviceResources.cpp index 4a73b52..a35a0db 100644 --- a/Samples/IntroGraphics/SimpleTexture/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleTexture/DeviceResources.cpp @@ -279,7 +279,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -315,10 +315,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -361,7 +357,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -398,25 +395,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/IntroGraphics/SimpleTexture/DeviceResources.h b/Samples/IntroGraphics/SimpleTexture/DeviceResources.h index 1f9a3a5..082b073 100644 --- a/Samples/IntroGraphics/SimpleTexture/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleTexture/DeviceResources.h @@ -12,6 +12,7 @@ namespace DX public: static constexpr unsigned int c_Enable4K_UHD = 0x1; static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_ReverseDepth = 0x8; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -35,6 +36,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -68,7 +70,6 @@ namespace DX } private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; diff --git a/Samples/IntroGraphics/SimpleTexture/SimpleTexture.cpp b/Samples/IntroGraphics/SimpleTexture/SimpleTexture.cpp index 98ad548..b5066a9 100644 --- a/Samples/IntroGraphics/SimpleTexture/SimpleTexture.cpp +++ b/Samples/IntroGraphics/SimpleTexture/SimpleTexture.cpp @@ -101,6 +101,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); diff --git a/Samples/IntroGraphics/SimpleTriangle/DeviceResources.cpp b/Samples/IntroGraphics/SimpleTriangle/DeviceResources.cpp index 4a73b52..a35a0db 100644 --- a/Samples/IntroGraphics/SimpleTriangle/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleTriangle/DeviceResources.cpp @@ -279,7 +279,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( @@ -315,10 +315,6 @@ void DeviceResources::CreateWindowSizeDependentResources() // Prepare the command list and render target for rendering. void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) { - // Wait until frame start is signaled - m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; - ThrowIfFailed(m_d3dDevice->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &m_framePipelineToken)); - // Reset command list and allocator. ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); @@ -361,7 +357,8 @@ void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, _In_opt_ const // Xbox apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. - MoveToNextFrame(); + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; } // Handle GPU suspend/resume @@ -398,25 +395,17 @@ void DeviceResources::WaitForGpu() noexcept } } -// Prepare to render the next frame. -void DeviceResources::MoveToNextFrame() +// For PresentX rendering, we should wait for the origin event just before processing input. +void DeviceResources::WaitForOrigin() { - // Schedule a Signal command in the queue. - const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; - ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); - - // Update the back buffer index. - m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; - - // If the next frame is not ready to be rendered yet, wait until it is ready. - if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); - std::ignore = WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); - } - - // Set the fence value for the next frame. - m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; + // Wait until frame start is signaled + m_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + ThrowIfFailed(m_d3dDevice->WaitFrameEventX( + D3D12XBOX_FRAME_EVENT_ORIGIN, + INFINITE, + nullptr, + D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, + &m_framePipelineToken)); } // Set frame interval and register for frame events diff --git a/Samples/IntroGraphics/SimpleTriangle/DeviceResources.h b/Samples/IntroGraphics/SimpleTriangle/DeviceResources.h index 1f9a3a5..082b073 100644 --- a/Samples/IntroGraphics/SimpleTriangle/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleTriangle/DeviceResources.h @@ -12,6 +12,7 @@ namespace DX public: static constexpr unsigned int c_Enable4K_UHD = 0x1; static constexpr unsigned int c_EnableQHD = 0x2; + static constexpr unsigned int c_ReverseDepth = 0x8; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, @@ -35,6 +36,7 @@ namespace DX void Suspend(); void Resume(); void WaitForGpu() noexcept; + void WaitForOrigin(); // Device Accessors. RECT GetOutputSize() const noexcept { return m_outputSize; } @@ -68,7 +70,6 @@ namespace DX } private: - void MoveToNextFrame(); void RegisterFrameEvents(); static constexpr size_t MAX_BACK_BUFFER_COUNT = 3; diff --git a/Samples/IntroGraphics/SimpleTriangle/SimpleTriangle.cpp b/Samples/IntroGraphics/SimpleTriangle/SimpleTriangle.cpp index 4325d36..85353b9 100644 --- a/Samples/IntroGraphics/SimpleTriangle/SimpleTriangle.cpp +++ b/Samples/IntroGraphics/SimpleTriangle/SimpleTriangle.cpp @@ -54,6 +54,8 @@ void Sample::Tick() { PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %llu", m_frame); + m_deviceResources->WaitForOrigin(); + m_timer.Tick([&]() { Update(m_timer); diff --git a/Samples/IntroGraphics/SimpleTriangleDesktop/DeviceResources.cpp b/Samples/IntroGraphics/SimpleTriangleDesktop/DeviceResources.cpp index 528a106..5d4abe0 100644 --- a/Samples/IntroGraphics/SimpleTriangleDesktop/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleTriangleDesktop/DeviceResources.cpp @@ -392,7 +392,7 @@ void DeviceResources::CreateWindowSizeDependentResources() D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = m_depthBufferFormat; - depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Depth = (m_options & c_ReverseDepth) ? 0.0f : 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(m_d3dDevice->CreateCommittedResource( diff --git a/Samples/IntroGraphics/SimpleTriangleDesktop/DeviceResources.h b/Samples/IntroGraphics/SimpleTriangleDesktop/DeviceResources.h index ad6efd5..b703802 100644 --- a/Samples/IntroGraphics/SimpleTriangleDesktop/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleTriangleDesktop/DeviceResources.h @@ -22,6 +22,7 @@ namespace DX public: static constexpr unsigned int c_AllowTearing = 0x1; static constexpr unsigned int c_EnableHDR = 0x2; + static constexpr unsigned int c_ReverseDepth = 0x4; DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, diff --git a/Samples/IntroGraphics/SimpleTriangleDesktop/SimpleTriangleDesktop.cpp b/Samples/IntroGraphics/SimpleTriangleDesktop/SimpleTriangleDesktop.cpp index bc5e03c..9b47a90 100644 --- a/Samples/IntroGraphics/SimpleTriangleDesktop/SimpleTriangleDesktop.cpp +++ b/Samples/IntroGraphics/SimpleTriangleDesktop/SimpleTriangleDesktop.cpp @@ -177,14 +177,6 @@ void Sample::Clear() #pragma region Message Handlers // Message handlers -void Sample::OnActivated() -{ -} - -void Sample::OnDeactivated() -{ -} - void Sample::OnSuspending() { } @@ -198,7 +190,7 @@ void Sample::OnResuming() void Sample::OnWindowMoved() { - auto r = m_deviceResources->GetOutputSize(); + auto const r = m_deviceResources->GetOutputSize(); m_deviceResources->WindowSizeChanged(r.right, r.bottom); } diff --git a/Samples/IntroGraphics/SimpleTriangleDesktop/SimpleTriangleDesktop.h b/Samples/IntroGraphics/SimpleTriangleDesktop/SimpleTriangleDesktop.h index 2150917..59fbb05 100644 --- a/Samples/IntroGraphics/SimpleTriangleDesktop/SimpleTriangleDesktop.h +++ b/Samples/IntroGraphics/SimpleTriangleDesktop/SimpleTriangleDesktop.h @@ -37,8 +37,8 @@ public: void OnDeviceRestored() override; // Messages - void OnActivated(); - void OnDeactivated(); + void OnActivated() {} + void OnDeactivated() {} void OnSuspending(); void OnResuming(); void OnWindowMoved(); diff --git a/Samples/IntroGraphics/SimpleTriangleDesktop/pch.h b/Samples/IntroGraphics/SimpleTriangleDesktop/pch.h index 03f121b..f6bd67a 100644 --- a/Samples/IntroGraphics/SimpleTriangleDesktop/pch.h +++ b/Samples/IntroGraphics/SimpleTriangleDesktop/pch.h @@ -10,7 +10,9 @@ #pragma once #include +#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0A00 +#endif #include // Use the C++ standard templated min/max diff --git a/Samples/Live/Achievements/Achievements.cpp b/Samples/Live/Achievements/Achievements.cpp index ca11e4f..be58122 100644 --- a/Samples/Live/Achievements/Achievements.cpp +++ b/Samples/Live/Achievements/Achievements.cpp @@ -119,7 +119,7 @@ void Sample::Initialize(HWND window, int width, int height) } else // Handle other error cases { - + m_log->Format(DirectX::Colors::Red, L"Xbox Live Error: 0x%08X\n", error); } }); diff --git a/Samples/Live/Achievements/Achievements.vcxproj b/Samples/Live/Achievements/Achievements.vcxproj index 4cf1930..1ec789e 100644 --- a/Samples/Live/Achievements/Achievements.vcxproj +++ b/Samples/Live/Achievements/Achievements.vcxproj @@ -498,7 +498,7 @@ - + diff --git a/Samples/Live/Achievements/Achievements.vcxproj.filters b/Samples/Live/Achievements/Achievements.vcxproj.filters index b69fe76..130c5d9 100644 --- a/Samples/Live/Achievements/Achievements.vcxproj.filters +++ b/Samples/Live/Achievements/Achievements.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -97,7 +97,7 @@ - + diff --git a/Samples/Live/Achievements/Achievements_Readme.docx b/Samples/Live/Achievements/Achievements_Readme.docx index ad3f0fa..9d20011 100644 Binary files a/Samples/Live/Achievements/Achievements_Readme.docx and b/Samples/Live/Achievements/Achievements_Readme.docx differ diff --git a/Samples/Live/Achievements/Main.cpp b/Samples/Live/Achievements/Main.cpp index 373302d..791cdcb 100644 --- a/Samples/Live/Achievements/Main.cpp +++ b/Samples/Live/Achievements/Main.cpp @@ -197,6 +197,9 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lp CloseHandle(g_plmSignalResume); #endif +#ifdef ATG_ENABLE_TELEMETRY + ATG::CleanupTelemetry(); +#endif XGameRuntimeUninitialize(); CoUninitialize(); @@ -391,7 +394,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); diff --git a/Samples/Live/Achievements/MicrosoftGame.Config b/Samples/Live/Achievements/MicrosoftGameConfig.mgc similarity index 93% rename from Samples/Live/Achievements/MicrosoftGame.Config rename to Samples/Live/Achievements/MicrosoftGameConfig.mgc index 8dbe902..6a4a672 100644 --- a/Samples/Live/Achievements/MicrosoftGame.Config +++ b/Samples/Live/Achievements/MicrosoftGameConfig.mgc @@ -1,5 +1,5 @@ - + 64353034 + 0000000040272D21 -#if _GRDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GRDK_VER < 0x55F00C58 /* GDK Edition 220300 */ +#error This sample requires the March 2022 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT diff --git a/Samples/Live/DownloadableContent/DLCPackage/Package_Scarlett/MicrosoftGame.config b/Samples/Live/DownloadableContent/DLCPackage/Package_Scarlett/MicrosoftGame.config deleted file mode 100644 index 2a37524..0000000 --- a/Samples/Live/DownloadableContent/DLCPackage/Package_Scarlett/MicrosoftGame.config +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - 6F9201BF - 9P96RFVJQ562 - - 9NQWJKKNHF1L - - Scarlett - - - - diff --git a/Samples/Live/DownloadableContent/DLCPackage/Package_XboxOne/MicrosoftGame.config b/Samples/Live/DownloadableContent/DLCPackage/Package_XboxOne/MicrosoftGame.config deleted file mode 100644 index a752536..0000000 --- a/Samples/Live/DownloadableContent/DLCPackage/Package_XboxOne/MicrosoftGame.config +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - 6F9201BF - 9P96RFVJQ562 - - 9NQWJKKNHF1L - - XboxOne - - - - diff --git a/Samples/Live/DownloadableContent/DLCPackagePC/Package/MicrosoftGame.config b/Samples/Live/DownloadableContent/DLCPackagePC/Package/MicrosoftGame.config deleted file mode 100644 index 2e464e9..0000000 --- a/Samples/Live/DownloadableContent/DLCPackagePC/Package/MicrosoftGame.config +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - 6F9201BF - 9P96RFVJQ562 - - 9NQWJKKNHF1L - - PC - - - - x64 - - - - - diff --git a/Samples/Live/DownloadableContent/DownloadableContent.cpp b/Samples/Live/DownloadableContent/DownloadableContent.cpp index 156035b..86bbc2d 100644 --- a/Samples/Live/DownloadableContent/DownloadableContent.cpp +++ b/Samples/Live/DownloadableContent/DownloadableContent.cpp @@ -75,6 +75,13 @@ Sample::Sample() noexcept(false) : Sample::~Sample() { + if (m_storeContext) + { + XStoreCloseContextHandle(m_storeContext); + } + + XPackageUnregisterPackageInstalled(m_packageInstallToken, true); + if (m_deviceResources) { m_deviceResources->WaitForGpu(); @@ -130,7 +137,7 @@ void Sample::Initialize(HWND window, int width, int height) m_liveResources->SetErrorHandler([this](HRESULT error) { - if (error == E_GAMEUSER_RESOLVE_USER_ISSUE_REQUIRED) + if (error == E_GAMEUSER_RESOLVE_USER_ISSUE_REQUIRED || error == E_GAMEUSER_NO_DEFAULT_USER) { m_liveResources->SignInWithUI(); } @@ -138,10 +145,6 @@ void Sample::Initialize(HWND window, int width, int height) { ErrorMessage("LiveResource error : E_GAMEUSER_NO_PACKAGE_IDENTITY\n"); } - else if (error == E_GAMEUSER_NO_DEFAULT_USER) - { - ErrorMessage("LiveResource error : E_GAMEUSER_NO_DEFAULT_USER\n"); - } else // Handle other error cases. { ErrorMessage("LiveResource error : 0x%08X\n", error); @@ -182,13 +185,15 @@ void Sample::RefreshStoreProducts() XStoreProductQueryHandle queryHandle = nullptr; + // This call occurs following output, this will be fixed by future update (bug:40153923) + // XERROR: HR:80070006 threadID:1060 Handle: already exists (00000000d5d1e1a0:StoreProductQuery) HRESULT hr = XStoreQueryAssociatedProductsResult( async, &queryHandle); if (static_cast(hr) == 0x803F6107) /* IAP_E_UNEXPECTED */ { - pThis->ErrorMessage("Config is invalid (Sandbox / ContentIdOverride / EKBIDOverride) : 0x%08X\n", hr); + pThis->ErrorMessage("User has no entitlement or configs are invalid (Sandbox / ContentIdOverride / EKBIDOverride) : 0x%08X\n", hr); delete async; pThis->m_isStoreEnumerating = false; return; @@ -208,8 +213,7 @@ void Sample::RefreshStoreProducts() { Sample* pThis = reinterpret_cast(context); - // BUG 30095480 : Currently hasDigitalDownload doesn't work. - //if (product->hasDigitalDownload) + if (product->hasDigitalDownload) { StoreProductDetails storeProduct(product); @@ -304,6 +308,7 @@ void Sample::RefreshStoreProducts() } + XStoreCloseProductsQueryHandle(queryHandle); delete async; pThis->m_isStoreEnumerating = false; }; @@ -376,7 +381,7 @@ void Sample::PurchaseStoreProduct(StoreProductDetails &package) if (FAILED(hr)) { - ErrorMessage("Failed to purchase: 0x%x\n", hr); + ErrorMessage("Failed to purchase : 0x%x\n", hr); delete reinterpret_cast(async->context); delete async; return; @@ -625,13 +630,16 @@ void Sample::RefreshInstalledPackages() { UnmountSelectedPackage(*package); button->GetTypedSubElementById(ID("DLC_Status"))->SetStyleId(ID("Unchecked")); + + SetBackgroundImage("Assets\\Unmounted.png"); } } }); - dlcButton->ButtonState().AddListenerWhen(UIButton::State::Focused, [this](UIButton* ) + dlcButton->ButtonState().AddListenerWhen(UIButton::State::Focused, [this](UIButton* button) { - m_legendText->SetDisplayText(UIDisplayString("[A] to Mount or Unmount Package, [Y] to Refresh, [LB] + [RB] to Toggle filter, [VIEW] to Close Sample")); + m_legendText->SetDisplayText(UIDisplayString("[A] to Mount or Unmount Package, [X] to Uninstall, [Y] to Refresh, [LB] + [RB] to Toggle filter, [VIEW] to Close Sample")); + m_currentFocusStoreId = button->GetTypedSubElementById(ID("DLC_StoreID"))->GetDisplayText(); }); } } @@ -649,91 +657,134 @@ PackageDetails* Sample::GetPackageDetail(const std::string &storeId) return nullptr; } -void Sample::MountSelectedPackage(PackageDetails &package) +HRESULT Sample::MountPackage(const char* packageIdentifier, XPackageMountHandle* mountHandle) { - struct Context - { - Sample *pThis; - PackageDetails *package; - }; - auto async = new XAsyncBlock{}; - async->queue = m_asyncQueue; - async->context = new Context{ this, &package }; - async->callback = [](XAsyncBlock *async) + + HRESULT hr = XPackageMountWithUiAsync(packageIdentifier, async); + + if (SUCCEEDED(hr)) { - auto &[pThis, package] = *reinterpret_cast(async->context); + // Wait for XPackageMountWithUiAsync. + hr = XAsyncGetStatus(async, true); - XStoreLicenseHandle license = {}; - auto result = XStoreAcquireLicenseForPackageResult(async, &license); - - if (SUCCEEDED(result)) + if (SUCCEEDED(hr)) { - bool isLicense = XStoreIsLicenseValid(license); + hr = XPackageMountWithUiResult(async, mountHandle); - debugPrint("%s %s\n", package->displayName.data(), isLicense ? "Licensed" : "No license"); - - if (isLicense) + if (FAILED(hr)) { - PackageEventContext *context = new PackageEventContext{ pThis, package->storeId }; - - auto token = pThis->RegisterPackageEvents(license, context); - - XPackageMountHandle mountHandle = {}; - result = XPackageMount(package->packageIdentifier.data(), &mountHandle); - - if (SUCCEEDED(result)) - { - package->isMounted = true; - package->button->GetTypedSubElementById(ID("DLC_Status"))->SetStyleId(ID("Checked")); - - pThis->AddNewMountedPackage(package->storeId, license, token, mountHandle, context); - } - else if (result == E_ACCESSDENIED) - { - XStoreCloseLicenseHandle(license); - pThis->ErrorMessage("Mounting failed. Cannot mount an app (%s): E_ACCESSDENIED\n", package->displayName.data()); - } - else if (result == E_GAMEPACKAGE_DLC_NOT_SUPPORTED) - { - XStoreCloseLicenseHandle(license); - pThis->ErrorMessage("Mounting failed. This package may target another device %s: 0x%08X\n", package->displayName.data(), result); - } - else - { - XStoreCloseLicenseHandle(license); - pThis->ErrorMessage("Error mounting package %s: 0x%08X\n", package->displayName.data(), result); - } + ErrorMessage("Mounting failed : %s : 0x%08X\n", packageIdentifier, hr); } - else - { - pThis->ErrorMessage("You don't have a license for %s.\n", package->displayName.data()); - } - pThis->RefreshInstalledPackages(); - pThis->m_needSetFocus = EnumFocusArea::InstalledPackages; - } - else if (static_cast(result) == 0x87E10BC6) /* LM_E_CONTENT_NOT_IN_CATALOG */ - { - pThis->ErrorMessage("XStoreAcquireLicenseForPackageResult failed: %s : LM_E_CONTENT_NOT_IN_CATALOG.\n", package->displayName.data()); } else { - pThis->ErrorMessage("XStoreAcquireLicenseForPackageResult failed: %s : 0x%08X\n", package->displayName.data(), result); + if (hr == E_ACCESSDENIED) + { + ErrorMessage("Mounting failed. Cannot access package : %s : E_ACCESSDENIED\n", packageIdentifier); + } + else if (hr == E_GAMEPACKAGE_DLC_NOT_SUPPORTED) + { + ErrorMessage("Mounting failed. This package may target another device : %s : E_GAMEPACKAGE_DLC_NOT_SUPPORTED\n", packageIdentifier); + } + else if (hr == E_ABORT) + { + ErrorMessage("Mounting failed. User canceled : %s : E_ABORT.\n", packageIdentifier); + } + else if (static_cast(hr) == 0x87DE2729 /* LM_E_OWNER_NOT_SIGNED_IN */) + { + ErrorMessage("Mounting failed. User has no entitlement : %s", packageIdentifier); + } + else + { + ErrorMessage("Mounting failed : %s : 0x%08X\n", packageIdentifier, hr); + } } - - package->isBusy = false; - - delete reinterpret_cast(async->context); - delete async; - }; - - if (FAILED(XStoreAcquireLicenseForPackageAsync(m_storeContext, package.packageIdentifier.data(), async))) - { - package.isBusy = false; - - delete reinterpret_cast(async->context); - delete async; } + + delete async; + + return hr; +} + +HRESULT Sample::AcquireLicense(const char* packageIdentifier, XStoreLicenseHandle* licenseHandle) +{ + auto async = new XAsyncBlock{}; + + HRESULT hr = XStoreAcquireLicenseForPackageAsync(m_storeContext, packageIdentifier, async); + + if (SUCCEEDED(hr)) + { + // Wait for XStoreAcquireLicenseForPackageAsync. + hr = XAsyncGetStatus(async, true); + + if (SUCCEEDED(hr)) + { + hr = XStoreAcquireLicenseForPackageResult(async, licenseHandle); + } + else + { + if (static_cast(hr) == 0x87E10BC6) /* LM_E_CONTENT_NOT_IN_CATALOG */ + { + ErrorMessage("AcquireLicense failed: %s : LM_E_CONTENT_NOT_IN_CATALOG.\n", packageIdentifier); + } + if (static_cast(hr) == 0x803F9006) /* LM_E_ENTITLED_USER_SIGNED_OUT */ + { + ErrorMessage("AcquireLicense failed: %s : LM_E_ENTITLED_USER_SIGNED_OUT.\n", packageIdentifier); + } + else + { + ErrorMessage("AcquireLicense failed: %s : 0x%08X\n", packageIdentifier, hr); + } + } + } + + delete async; + + return hr; +} + +void Sample::MountSelectedPackage(PackageDetails &package) +{ + XStoreLicenseHandle license = {}; + + HRESULT hr = AcquireLicense(package.packageIdentifier.data(), &license); + + if (SUCCEEDED(hr)) + { + bool isLicense = XStoreIsLicenseValid(license); + + debugPrint("%s %s\n", package.displayName.data(), isLicense ? "Licensed" : "No license"); + + if (isLicense) + { + PackageEventContext* pec = new PackageEventContext{ this, package.storeId }; + + auto token = RegisterPackageEvents(license, pec); + + XPackageMountHandle mountHandle = {}; + + hr = MountPackage(package.packageIdentifier.data(), &mountHandle); + + if (SUCCEEDED(hr)) + { + package.isMounted = true; + package.button->GetTypedSubElementById(ID("DLC_Status"))->SetStyleId(ID("Checked")); + + AddNewMountedPackage(package.storeId, license, token, mountHandle, pec); + } + else + { + delete pec; + XStoreCloseLicenseHandle(license); + } + + RefreshInstalledPackages(); + m_needSetFocus = EnumFocusArea::InstalledPackages; + } + } + + package.isBusy = false; } void Sample::UnmountSelectedPackage(PackageDetails &package) @@ -833,44 +884,9 @@ void Sample::AddNewMountedPackage(std::string &storeId, XStoreLicenseHandle lice debugPrint("DLC path : %s\n", path); - HANDLE hFile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); - - if (hFile == INVALID_HANDLE_VALUE) - { - ErrorMessage("Failed to open %s\n", path); - delete[] path; - return; - } - - // Get file size - FILE_STANDARD_INFO fileInfo; - if (GetFileInformationByHandleEx(hFile, FileStandardInfo, &fileInfo, sizeof(fileInfo)) == FALSE) - { - ErrorMessage("Failed to get the file size %s\n", path); - delete[] path; - CloseHandle(hFile); - return; - } - - LARGE_INTEGER fileSize = fileInfo.EndOfFile; - - // Allocate the buffer - std::unique_ptr buffer; - buffer.reset(new uint8_t[fileSize.LowPart]); - - DWORD bytesRead; - if (ReadFile(hFile, buffer.get(), fileSize.LowPart, &bytesRead, nullptr) == FALSE) - { - ErrorMessage("ReadFile Failed %s\n", path); - delete[] path; - CloseHandle(hFile); - return; - } + SetBackgroundImage(path); delete[] path; - CloseHandle(hFile); - - m_backgroundImage->UseTextureData(buffer.get(), fileSize.LowPart); } PackageMountInfo* Sample::GetPackageMountInfo(const std::string &storeId) @@ -884,6 +900,22 @@ PackageMountInfo* Sample::GetPackageMountInfo(const std::string &storeId) return nullptr; } + +void Sample::UninstallPackage(PackageDetails& package) +{ + if (XPackageUninstallPackage(package.packageIdentifier.data())) + { + debugPrint("Package %s uninstalled.\n", package.packageIdentifier.data()); + } + else + { + ErrorMessage("XPackageUninstallPackage failed : %s\n", package.packageIdentifier.data()); + } + + RefreshInstalledPackages(); + RefreshStoreProducts(); +} + #pragma endregion #pragma region UI Methods @@ -915,6 +947,44 @@ void Sample::ResetStoreButton(std::shared_ptr button) SetDisplayText(UIDisplayString("")); } +void Sample::SetBackgroundImage(const char* filename) +{ + HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + ErrorMessage("Failed to open %s\n", filename); + return; + } + + // Get file size + FILE_STANDARD_INFO fileInfo; + if (GetFileInformationByHandleEx(hFile, FileStandardInfo, &fileInfo, sizeof(fileInfo)) == FALSE) + { + ErrorMessage("Failed to get the file size %s\n", filename); + CloseHandle(hFile); + return; + } + + LARGE_INTEGER fileSize = fileInfo.EndOfFile; + + // Allocate the buffer + std::unique_ptr buffer; + buffer.reset(new uint8_t[fileSize.LowPart]); + + DWORD bytesRead; + if (ReadFile(hFile, buffer.get(), fileSize.LowPart, &bytesRead, nullptr) == FALSE) + { + ErrorMessage("ReadFile Failed %s\n", filename); + CloseHandle(hFile); + return; + } + + CloseHandle(hFile); + + m_backgroundImage->UseTextureData(buffer.get(), fileSize.LowPart); +} + void Sample::ErrorMessage(std::string_view format, ...) { const size_t bufferSize = 2048; @@ -994,6 +1064,17 @@ void Sample::Update(DX::StepTimer const& timer) m_twistMenu->DecrementSelectedItem(); } + if (buttons.x == GamePad::ButtonStateTracker::PRESSED || + keys.IsKeyPressed(DirectX::Keyboard::Keys::X)) + { + if (m_currentFocusStoreId != "") + { + PackageDetails* package = GetPackageDetail(m_currentFocusStoreId); + UninstallPackage(*package); + m_currentFocusStoreId = ""; + } + } + if (buttons.y == GamePad::ButtonStateTracker::PRESSED || keys.IsKeyPressed(DirectX::Keyboard::Keys::Y)) { diff --git a/Samples/Live/DownloadableContent/DownloadableContent.h b/Samples/Live/DownloadableContent/DownloadableContent.h index 00f67c7..56f7a79 100644 --- a/Samples/Live/DownloadableContent/DownloadableContent.h +++ b/Samples/Live/DownloadableContent/DownloadableContent.h @@ -175,6 +175,8 @@ public: // DLC Methods void RefreshInstalledPackages(); + HRESULT MountPackage(const char* packageIdentifier, XPackageMountHandle* mountHandle); + HRESULT AcquireLicense(const char* packageIdentifier, XStoreLicenseHandle* licenseHandle); void MountSelectedPackage(PackageDetails &package); void UnmountSelectedPackage(PackageDetails &package); XTaskQueueRegistrationToken RegisterPackageEvents(XStoreLicenseHandle license, PackageEventContext *context); @@ -182,6 +184,7 @@ public: void AddNewMountedPackage(std::string &storeId, XStoreLicenseHandle license, XTaskQueueRegistrationToken token, XPackageMountHandle mountHandle, PackageEventContext *context); PackageMountInfo* GetPackageMountInfo(const std::string &storeId); PackageDetails* GetPackageDetail(const std::string &storeId); + void UninstallPackage(PackageDetails& package); private: @@ -195,6 +198,7 @@ private: void InitializeUI(); void ResetStoreButton(std::shared_ptr button); + void SetBackgroundImage(const char* filename); void ErrorMessage(std::string_view format, ...); // UIStyleManager::D3DResourcesProvider interface methods @@ -247,6 +251,7 @@ private: std::vector m_storeDetailList; bool m_isStoreEnumerating; + std::string m_currentFocusStoreId; std::string m_lastSelectStoreId; EnumFocusArea m_needSetFocus; diff --git a/Samples/Live/DownloadableContent/DownloadableContent.vcxproj b/Samples/Live/DownloadableContent/DownloadableContent.vcxproj index 57b08ab..02e8660 100644 --- a/Samples/Live/DownloadableContent/DownloadableContent.vcxproj +++ b/Samples/Live/DownloadableContent/DownloadableContent.vcxproj @@ -495,14 +495,11 @@ - - - + + + Document - - Designer - @@ -579,11 +576,11 @@ true false - + true false - + true false @@ -676,6 +673,32 @@ + + + true + true + true + true + true + true + + + true + true + true + true + true + true + + + true + true + true + true + true + true + + diff --git a/Samples/Live/DownloadableContent/DownloadableContent.vcxproj.filters b/Samples/Live/DownloadableContent/DownloadableContent.vcxproj.filters index 948f084..0f975fb 100644 --- a/Samples/Live/DownloadableContent/DownloadableContent.vcxproj.filters +++ b/Samples/Live/DownloadableContent/DownloadableContent.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -164,7 +164,7 @@ DLCPackage\Package_XboxOne - + DLCPackage\Package_XboxOne @@ -185,7 +185,7 @@ DLCPackage\Package_Scarlett - + DLCPackage\Package_Scarlett @@ -195,7 +195,7 @@ DLCPackagePC - + DLCPackagePC\Package @@ -220,9 +220,6 @@ DLCPackagePC\Package\Assets - - - Assets @@ -314,4 +311,9 @@ Assets + + + + + \ No newline at end of file diff --git a/Samples/Live/DownloadableContent/Main.cpp b/Samples/Live/DownloadableContent/Main.cpp index 9376010..1f614c2 100644 --- a/Samples/Live/DownloadableContent/Main.cpp +++ b/Samples/Live/DownloadableContent/Main.cpp @@ -378,7 +378,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); diff --git a/Samples/Live/DownloadableContent/MicrosoftGame.Config b/Samples/Live/DownloadableContent/MicrosoftGameConfig_PC.mgc similarity index 82% rename from Samples/Live/DownloadableContent/MicrosoftGame.Config rename to Samples/Live/DownloadableContent/MicrosoftGameConfig_PC.mgc index 1e4ade5..b03fef5 100644 --- a/Samples/Live/DownloadableContent/MicrosoftGame.Config +++ b/Samples/Live/DownloadableContent/MicrosoftGameConfig_PC.mgc @@ -1,16 +1,18 @@ - + - + 6F9201BF 9NQWJKKNHF1L + 0000000040380102 @@ -18,7 +20,7 @@ - d730ab4d-8c24-4963-ad8f-4a292b448997 + DD755A56-F89D-443F-81C9-47412CA0E048 00000000-0000-0000-0000-000000000001 diff --git a/Samples/Live/DownloadableContent/MicrosoftGameConfig_Scarlett.mgc b/Samples/Live/DownloadableContent/MicrosoftGameConfig_Scarlett.mgc new file mode 100644 index 0000000..3b65e3f --- /dev/null +++ b/Samples/Live/DownloadableContent/MicrosoftGameConfig_Scarlett.mgc @@ -0,0 +1,38 @@ + + + + + + + + + + + 6F9201BF + 9NQWJKKNHF1L + 0000000040380102 + + + + XboxOne + + + + D730AB4D-8C24-4963-AD8F-4A292B448997 + 00000000-0000-0000-0000-000000000001 + + + + + diff --git a/Samples/Live/DownloadableContent/MicrosoftGameConfig_XboxOne.mgc b/Samples/Live/DownloadableContent/MicrosoftGameConfig_XboxOne.mgc new file mode 100644 index 0000000..f1f11db --- /dev/null +++ b/Samples/Live/DownloadableContent/MicrosoftGameConfig_XboxOne.mgc @@ -0,0 +1,38 @@ + + + + + + + + + + + 6F9201BF + 9NQWJKKNHF1L + 0000000040380102 + + + + XboxOne + + + + D730AB4D-8C24-4963-AD8F-4A292B448997 + 00000000-0000-0000-0000-000000000001 + + + + + diff --git a/Samples/Live/DownloadableContent/ReadMe.docx b/Samples/Live/DownloadableContent/ReadMe.docx index 05509f2..841c021 100644 Binary files a/Samples/Live/DownloadableContent/ReadMe.docx and b/Samples/Live/DownloadableContent/ReadMe.docx differ diff --git a/Samples/Live/DownloadableContent/pch.h b/Samples/Live/DownloadableContent/pch.h index 091e9e1..5296825 100644 --- a/Samples/Live/DownloadableContent/pch.h +++ b/Samples/Live/DownloadableContent/pch.h @@ -41,8 +41,8 @@ #include -#if _GRDK_VER < 0x4A6110CC /* GDK Edition 201100 */ -#error This sample requires the November 2020 GDK or later +#if _GRDK_VER < 0x55F00C58 /* GDK Edition 220300 */ +#error This sample requires the March 2022 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT diff --git a/Samples/Live/Fundamentals_Desktop/Fundamentals_Desktop.vcxproj b/Samples/Live/Fundamentals_Desktop/Fundamentals_Desktop.vcxproj index abfadbb..a7b7096 100644 --- a/Samples/Live/Fundamentals_Desktop/Fundamentals_Desktop.vcxproj +++ b/Samples/Live/Fundamentals_Desktop/Fundamentals_Desktop.vcxproj @@ -213,7 +213,7 @@ xcopy /Y /I /E "..\..\..\Media\Fonts\*.spritefont" "$(TargetDir)" - + diff --git a/Samples/Live/Fundamentals_Desktop/Fundamentals_Desktop.vcxproj.filters b/Samples/Live/Fundamentals_Desktop/Fundamentals_Desktop.vcxproj.filters index d366335..d0091f9 100644 --- a/Samples/Live/Fundamentals_Desktop/Fundamentals_Desktop.vcxproj.filters +++ b/Samples/Live/Fundamentals_Desktop/Fundamentals_Desktop.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -81,7 +81,7 @@ - + diff --git a/Samples/Live/Fundamentals_Desktop/Main.cpp b/Samples/Live/Fundamentals_Desktop/Main.cpp index 3568389..e4057f2 100644 --- a/Samples/Live/Fundamentals_Desktop/Main.cpp +++ b/Samples/Live/Fundamentals_Desktop/Main.cpp @@ -294,7 +294,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); diff --git a/Samples/Live/Fundamentals_Desktop/MicrosoftGame.Config b/Samples/Live/Fundamentals_Desktop/MicrosoftGameConfig.mgc similarity index 93% rename from Samples/Live/Fundamentals_Desktop/MicrosoftGame.Config rename to Samples/Live/Fundamentals_Desktop/MicrosoftGameConfig.mgc index 9beb526..b828fbd 100644 --- a/Samples/Live/Fundamentals_Desktop/MicrosoftGame.Config +++ b/Samples/Live/Fundamentals_Desktop/MicrosoftGameConfig.mgc @@ -1,5 +1,5 @@ - + 7325F784 + 00000000442675A9 -#if _GRDK_VER < 0x47BB2070 /* GDK Edition 191102 */ -#error This sample requires the November 2020 GDK QFE2 or later +#if _GRDK_VER < 0x55F00C58 /* GDK Edition 220300 */ +#error This sample requires the March 2022 GDK or later #endif #include diff --git a/Samples/Live/InGameStore/InGameStore.cpp b/Samples/Live/InGameStore/InGameStore.cpp index b62c066..cf560b7 100644 --- a/Samples/Live/InGameStore/InGameStore.cpp +++ b/Samples/Live/InGameStore/InGameStore.cpp @@ -677,7 +677,8 @@ void Sample::QueryCatalog() XStoreProductKind::Consumable | XStoreProductKind::Durable | XStoreProductKind::Game | - XStoreProductKind::UnmanagedConsumable; + XStoreProductKind::UnmanagedConsumable | + XStoreProductKind::Pass; HRESULT hr = XStoreQueryAssociatedProductsAsync( m_xStoreContext, @@ -762,7 +763,8 @@ void Sample::QueryCollections() XStoreProductKind::Consumable | XStoreProductKind::Durable | XStoreProductKind::Game | - XStoreProductKind::UnmanagedConsumable; + XStoreProductKind::UnmanagedConsumable | + XStoreProductKind::Pass; HRESULT hr = XStoreQueryEntitledProductsAsync( m_xStoreContext, diff --git a/Samples/Live/InGameStore/InGameStore.vcxproj b/Samples/Live/InGameStore/InGameStore.vcxproj index 1b4bbba..0844137 100644 --- a/Samples/Live/InGameStore/InGameStore.vcxproj +++ b/Samples/Live/InGameStore/InGameStore.vcxproj @@ -1,4 +1,4 @@ - + @@ -627,7 +627,7 @@ - + Designer diff --git a/Samples/Live/InGameStore/InGameStore.vcxproj.filters b/Samples/Live/InGameStore/InGameStore.vcxproj.filters index 856c7b1..a06cacf 100644 --- a/Samples/Live/InGameStore/InGameStore.vcxproj.filters +++ b/Samples/Live/InGameStore/InGameStore.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -103,7 +103,7 @@ - + diff --git a/Samples/Live/InGameStore/Main.cpp b/Samples/Live/InGameStore/Main.cpp index 280e2eb..c0aeb2c 100644 --- a/Samples/Live/InGameStore/Main.cpp +++ b/Samples/Live/InGameStore/Main.cpp @@ -401,7 +401,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP); SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); diff --git a/Samples/Live/InGameStore/MicrosoftGame.Config b/Samples/Live/InGameStore/MicrosoftGameConfig.mgc similarity index 94% rename from Samples/Live/InGameStore/MicrosoftGame.Config rename to Samples/Live/InGameStore/MicrosoftGameConfig.mgc index 6738ee6..e7267a4 100644 --- a/Samples/Live/InGameStore/MicrosoftGame.Config +++ b/Samples/Live/InGameStore/MicrosoftGameConfig.mgc @@ -1,5 +1,5 @@ - + 62ab3c24 + 000000004C2690C8 9NTL0QDWZ4FS diff --git a/Samples/Live/InGameStore/ReadMe.docx b/Samples/Live/InGameStore/ReadMe.docx index 2569517..2aa63e5 100644 Binary files a/Samples/Live/InGameStore/ReadMe.docx and b/Samples/Live/InGameStore/ReadMe.docx differ diff --git a/Samples/Live/InGameStore/pch.h b/Samples/Live/InGameStore/pch.h index 413a993..bfa70fc 100644 --- a/Samples/Live/InGameStore/pch.h +++ b/Samples/Live/InGameStore/pch.h @@ -41,8 +41,8 @@ #include -#if _GRDK_VER < 0x4A610D2B /* GXDK Edition 200600 */ -#error This sample requires the June 2020 GDK or later +#if _GRDK_VER < 0x55F00C58 /* GDK Edition 220300 */ +#error This sample requires the March 2022 GDK or later #endif #ifdef _GAMING_XBOX_SCARLETT diff --git a/Samples/Live/LeaderboardsEventBased/Assets/SampleUI.csv b/Samples/Live/LeaderboardsEventBased/Assets/SampleUI.csv index 68a92f2..14e55d2 100644 --- a/Samples/Live/LeaderboardsEventBased/Assets/SampleUI.csv +++ b/Samples/Live/LeaderboardsEventBased/Assets/SampleUI.csv @@ -1,6 +1,6 @@ #ITEM,ID,X,Y,DX,DY,PARAMETERS CUSTOM_OVERLAY,2000,0,0,1920,1080 -LEGEND,2001,35,830,625,350,[DPad] or Up/Down Arrows - Select a scenario|[A] or Enter - Run the query|[X] or 'E' - Send game play event|[Y] or 'T' - Toggle Leaderboard type|[LB][RB] or Left/Right Arrows - Leaderboard / Stats Query|[View] or Esc Exit,SMALL +LEGEND,2001,35,830,625,350,[DPad] or UP/DOWN Arrows - Select a scenario|[A] or ENTER - Run the query|[X] or SPACE - Send game play event|[Y] or F1 - Toggle Leaderboard type|[LB][RB] or F2 - Leaderboard / Stats Query|[View] or ESC - Exit,SMALL # Console Labels LABEL,2002,525,150,300,50,Log,LEFT;SMALL diff --git a/Samples/Live/LeaderboardsEventBased/LeaderboardsEventBased.cpp b/Samples/Live/LeaderboardsEventBased/LeaderboardsEventBased.cpp index 7a1c036..2047a3d 100644 --- a/Samples/Live/LeaderboardsEventBased/LeaderboardsEventBased.cpp +++ b/Samples/Live/LeaderboardsEventBased/LeaderboardsEventBased.cpp @@ -31,6 +31,13 @@ void Sample::QueryLeaderboards( { XblSocialGroupType queryGroupType = isGlobalLeaderboard ? XblSocialGroupType::None : XblSocialGroupType::People; + if (!m_liveResources->GetLiveContext()) + { + m_resultConsole->Clear(); + m_resultConsole->WriteLine(L"No user is signed in."); + return; + } + m_logConsole->Clear(); m_logConsole->Format(L"** Query Leaderboard: %S / Stat: %S / Global: %lu\n", leaderboardName.c_str(), statName.c_str(), isGlobalLeaderboard); @@ -135,47 +142,6 @@ void Sample::ProcessLeaderboardResults(XAsyncBlock *async) } } - -void Sample::RenderLeaderboardsResults(LeaderboardsQueryContext *ctx) -{ - std::stringstream ss; - - if (ctx->page == 0) - { - // render header columns - ss << std::setw(8) << "Rank"; ss << std::setw(0) << " |"; - ss << std::setw(16) << "Gamer Tag"; - - for (size_t i = 0; i < ctx->result->columnsCount; i++) - { - ss << std::setw(0) << " |"; - ss << std::setw(i == 0 ? 32 : 18) << ctx->result->columns[i].statName; - } - ss << std::endl; - } - - // render all rows - for (size_t i = 0; i < ctx->result->rowsCount; i++) - { - ss << std::setw(8) << ctx->result->rows[i].rank; ss << std::setw(0) << " |"; - ss << std::setw(16) << ctx->result->rows[i].gamertag; - for (size_t j = 0; j < ctx->result->rows[i].columnValuesCount; j++) - { - ss << std::setw(0) << " |"; - ss << std::setw(j == 0 ? 32 : 18) << ctx->result->rows[i].columnValues[j]; - } - - if (i + 1 < ctx->result->rowsCount) { ss << std::endl; } - } - - if(ctx->page == 0) - { - m_resultConsole->Clear(); - } - - m_resultConsole->WriteLine(DX::Utf8ToWide(ss.str()).c_str()); -} - // Queries an individual statistic for the current user void Sample::QueryStatistics(const std::string &statName) { @@ -206,7 +172,7 @@ void Sample::QueryStatistics(const std::string &statName) hr = XblUserStatisticsGetSingleUserStatisticResultSize(async, &size); if (SUCCEEDED(hr)) { - buffer.reserve(size); + buffer.resize(size); hr = XblUserStatisticsGetSingleUserStatisticResult(async, size, buffer.data(), &result, &size); if (SUCCEEDED(hr)) { @@ -239,24 +205,6 @@ void Sample::QueryStatistics(const std::string &statName) } } -void Sample::RenderStatisticsResult(XblUserStatisticsResult *res) -{ - std::stringstream ss; - - for (uint32_t i = 0; i < res->serviceConfigStatisticsCount; i++) - { - for (uint32_t j = 0; j < res->serviceConfigStatistics[i].statisticsCount; j++) - { - ss << std::setw(20) << res->serviceConfigStatistics[i].statistics[j].statisticName; - ss << std::setw(12) << res->serviceConfigStatistics[i].statistics[j].statisticType; - ss << std::setw(12) << res->serviceConfigStatistics[i].statistics[j].value; - ss << std::endl; - } - } - - m_resultConsole->Clear(); - m_resultConsole->WriteLine(DX::Utf8ToWide(ss.str()).c_str()); -} // Simulate a play session void Sample::PlayGame() @@ -276,100 +224,7 @@ void Sample::PlayGame() } } -void Sample::SetupUI() -{ - using namespace ATG; - - wchar_t result[MAX_PATH]; - DX::FindMediaFile(result, MAX_PATH, L".\\Assets\\SampleUI.csv"); - m_ui->LoadLayout(result, L".\\Assets\\"); - - s_mainPanel = m_ui->FindPanel(c_sampleUIPanel); - - s_labels.emplace(c_pageTitleText, m_ui->FindControl(c_sampleUIPanel, c_pageTitleLabel)); - s_labels.emplace(c_pageDescText, m_ui->FindControl(c_sampleUIPanel, c_modeLabel)); - s_labels.emplace(c_leaderboardType, m_ui->FindControl(c_sampleUIPanel, c_leaderboardType)); - - auto statsMaze = m_ui->FindControl