Integrating up through commit 90f050496

This commit is contained in:
alexpete
2021-04-07 14:03:29 -07:00
parent 8f2ed080a9
commit c2cbd430fe
2694 changed files with 285622 additions and 176874 deletions
@@ -15,7 +15,8 @@
namespace AZ::IO
{
bool CollectIoHardwareInformation(HardwareInformation& info, [[maybe_unused]] bool includeAllHardware)
bool CollectIoHardwareInformation(
HardwareInformation& info, [[maybe_unused]] bool includeAllHardware, [[maybe_unused]] bool reportHardware)
{
// The numbers below are based on common defaults from a local hardware survey.
info.m_maxPageSize = 4096;
@@ -14,9 +14,8 @@
namespace AZ::Utils
{
AZ::IO::FixedMaxPathString GetEngineManifestPath()
AZ::IO::FixedMaxPathString GetO3deManifestDirectory()
{
return {};
}
} // namespace AZ::Utils
} // namespace AZ::Utils
@@ -25,7 +25,7 @@ namespace AZ
void NativeErrorMessageBox(const char*, const char*) {}
AZ::IO::FixedMaxPathString GetEngineManifestPath()
AZ::IO::FixedMaxPathString GetO3deManifestDirectory()
{
if (const char* homePath = std::getenv("HOME"); homePath != nullptr)
{
@@ -33,7 +33,6 @@ namespace AZ
if (!path.empty())
{
path /= ".o3de";
path /= "o3de_manifest.json";
}
return path.Native();
}
@@ -31,6 +31,7 @@ namespace AZ::IO
options.m_enableUnbufferedReads = m_enableUnbufferedReads;
options.m_enableSharing = m_enableFileSharing;
options.m_hasSeekPenalty = drive.m_hasSeekPenalty;
options.m_minimalReporting = m_minimalReporting;
AZStd::vector<AZStd::string_view> drivePaths(drive.m_paths.begin(), drive.m_paths.end());
AZ_Assert(!drive.m_paths.empty(), "Expected at least one drive path.");
@@ -59,7 +60,8 @@ namespace AZ::IO
->Field("MaxMetaDataCache", &WindowsStorageDriveConfig::m_maxMetaDataCache)
->Field("Overcommit", &WindowsStorageDriveConfig::m_overcommit)
->Field("EnableFileSharing", &WindowsStorageDriveConfig::m_enableFileSharing)
->Field("EnableUnbufferedReads", &WindowsStorageDriveConfig::m_enableUnbufferedReads);
->Field("EnableUnbufferedReads", &WindowsStorageDriveConfig::m_enableUnbufferedReads)
->Field("MinimalReporting", &WindowsStorageDriveConfig::m_minimalReporting);
}
}
} // namespace AZ::IO
@@ -34,5 +34,6 @@ namespace AZ::IO
AZ::u32 m_overcommit{ 8 };
bool m_enableFileSharing{ false };
bool m_enableUnbufferedReads{ true };
bool m_minimalReporting{ false };
};
} // namespace AZ::IO
@@ -41,6 +41,7 @@ namespace AZ::IO
: m_hasSeekPenalty(true)
, m_enableUnbufferedReads(true)
, m_enableSharing(false)
, m_minimalReporting(false)
{}
//
@@ -102,7 +103,10 @@ namespace AZ::IO
m_name += m_drivePaths[i].substr(0, m_drivePaths[i].length()-1);
}
m_name += ')';
AZ_Printf("Streamer", "%s created.\n", m_name.c_str());
if (!m_constructionOptions.m_minimalReporting)
{
AZ_Printf("Streamer", "%s created.\n", m_name.c_str());
}
if (m_physicalSectorSize == 0)
{
@@ -160,7 +164,10 @@ namespace AZ::IO
::CloseHandle(file);
}
}
AZ_Printf("Streamer", "%s destroyed.\n", m_name.c_str());
if (!m_constructionOptions.m_minimalReporting)
{
AZ_Printf("Streamer", "%s destroyed.\n", m_name.c_str());
}
}
void StorageDriveWin::PrepareRequest(FileRequest* request)
@@ -483,7 +490,7 @@ namespace AZ::IO
// Remove any alertable IO completion notifications that could be queued by the IO Manager.
if (!::SetFileCompletionNotificationModes(file, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS))
{
AZ_Printf("StorageDriveWin", "Failed to remove alertable IO completion notifications. (Error: %u)\n", ::GetLastError());
AZ_Warning("StorageDriveWin", false, "Failed to remove alertable IO completion notifications. (Error: %u)\n", ::GetLastError());
}
if (m_fileCache_handles[cacheIndex] != INVALID_HANDLE_VALUE)
@@ -651,15 +658,6 @@ namespace AZ::IO
#endif // AZ_STREAMER_ADD_EXTRA_PROFILING_INFO
}
// Keep this, it helps to see the critical info about every read.
//AZ_Printf("StorageDriveWin", "FileRead: addr: 0x%p size: %zu offs: %zu alloc: %s direct: %.2f%% '%s'\n",
// data->m_output,
// data->m_size,
// data->m_offset,
// (isAligned) ? "Yes" : "No",
// m_directReadsPercentageStat.GetAverage() * 100.0,
// data->m_path.GetRelativePath());
FileReadStatus& readStatus = m_readSlots_statusInfo[readSlot];
LPOVERLAPPED overlapped = &readStatus.m_overlapped;
overlapped->Offset = aznumeric_caster(readOffs);
@@ -678,7 +676,7 @@ namespace AZ::IO
DWORD error = ::GetLastError();
if (error != ERROR_IO_PENDING)
{
AZ_Printf("StorageDriveWin", "::ReadFile failed with error: %u\n", error);
AZ_Warning("StorageDriveWin", false, "::ReadFile failed with error: %u\n", error);
m_context->GetStreamerThreadSynchronizer().DestroyEventHandle(overlapped->hEvent);
@@ -47,6 +47,9 @@ namespace AZ::IO
//! while in use by AZ::IO::Streamer. File sharing can negatively impact performance and is recommended for
//! development only.
u8 m_enableSharing : 1;
//! If true, only information that's explicitly requested or issues are reported. If false, status information
//! such as when drives are created and destroyed is reported as well.
u8 m_minimalReporting : 1;
};
//! Creates an instance of a storage device that's optimized for use on Windows.
@@ -34,7 +34,7 @@ namespace AZ::IO
return value;
}
static void CollectIoAdaptor(HANDLE deviceHandle, DriveInformation& info, const char* driveName)
static void CollectIoAdaptor(HANDLE deviceHandle, DriveInformation& info, const char* driveName, bool reportHardware)
{
STORAGE_ADAPTER_DESCRIPTOR adapterDescriptor{};
STORAGE_PROPERTY_QUERY query{};
@@ -71,17 +71,21 @@ namespace AZ::IO
DWORD pageSize = NextPowerOfTwo(adapterDescriptor.MaximumTransferLength / adapterDescriptor.MaximumPhysicalPages);
AZ_Printf("Streamer",
"Adapter for drive '%s':\n"
" Bus: %s %i.%i\n"
" Max transfer: %.3f kb\n"
" Page size: %i kb for %i pages\n"
" Supports queuing: %s\n",
driveName,
info.m_profile.c_str(), adapterDescriptor.BusMajorVersion, adapterDescriptor.BusMinorVersion,
(1.0f / 1024.0f) * adapterDescriptor.MaximumTransferLength,
pageSize, adapterDescriptor.MaximumPhysicalPages,
adapterDescriptor.CommandQueueing ? "Yes" : "No");
if (reportHardware)
{
AZ_Printf(
"Streamer",
"Adapter for drive '%s':\n"
" Bus: %s %i.%i\n"
" Max transfer: %.3f kb\n"
" Page size: %i kb for %i pages\n"
" Supports queuing: %s\n",
driveName,
info.m_profile.c_str(), adapterDescriptor.BusMajorVersion, adapterDescriptor.BusMinorVersion,
(1.0f / 1024.0f) * adapterDescriptor.MaximumTransferLength,
pageSize, adapterDescriptor.MaximumPhysicalPages,
adapterDescriptor.CommandQueueing ? "Yes" : "No");
}
info.m_maxTransfer = adapterDescriptor.MaximumTransferLength;
info.m_pageSize = pageSize;
@@ -89,7 +93,7 @@ namespace AZ::IO
}
}
static void AppendDriveTypeToProfile(HANDLE deviceHandle, DriveInformation& information)
static void AppendDriveTypeToProfile(HANDLE deviceHandle, DriveInformation& information, bool reportHardware)
{
// Check for support for the TRIM command. This command is exclusively used by SSD drives so can be used to
// tell the difference between SSD and HDD. Since these are the only 2 types supported right now, no further
@@ -105,18 +109,24 @@ namespace AZ::IO
&trimDescriptor, sizeof(trimDescriptor), &bytesReturned, nullptr))
{
information.m_profile += trimDescriptor.TrimEnabled ? "_SSD" : "_HDD";
AZ_Printf("Streamer",
" Drive type: %s\n",
trimDescriptor.TrimEnabled ? "SSD" : "HDD");
if (reportHardware)
{
AZ_Printf("Streamer",
" Drive type: %s\n",
trimDescriptor.TrimEnabled ? "SSD" : "HDD");
}
}
else
{
AZ_Printf("Streamer",
" Drive type couldn't be determined.");
if (reportHardware)
{
AZ_Printf("Streamer", " Drive type couldn't be determined.");
}
}
}
static void CollectAlignmentRequirements(HANDLE deviceHandle, DriveInformation& information)
static void CollectAlignmentRequirements(HANDLE deviceHandle, DriveInformation& information, bool reportHardware)
{
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR alignmentDescriptor{};
STORAGE_PROPERTY_QUERY query{};
@@ -129,15 +139,19 @@ namespace AZ::IO
{
information.m_physicalSectorSize = aznumeric_caster(alignmentDescriptor.BytesPerPhysicalSector);
information.m_logicalSectorSize = aznumeric_caster(alignmentDescriptor.BytesPerLogicalSector);
AZ_Printf("Streamer",
" Physical sector size: %i bytes\n"
" Logical sector size: %i bytes\n",
alignmentDescriptor.BytesPerPhysicalSector,
alignmentDescriptor.BytesPerLogicalSector);
if (reportHardware)
{
AZ_Printf(
"Streamer",
" Physical sector size: %i bytes\n"
" Logical sector size: %i bytes\n",
alignmentDescriptor.BytesPerPhysicalSector,
alignmentDescriptor.BytesPerLogicalSector);
}
}
}
static void CollectDriveInfo(HANDLE deviceHandle, const char* driveName)
static void CollectDriveInfo(HANDLE deviceHandle, const char* driveName, bool reportHardware)
{
STORAGE_DEVICE_DESCRIPTOR sizeRequest{};
STORAGE_PROPERTY_QUERY query{};
@@ -154,21 +168,24 @@ namespace AZ::IO
if (::DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query),
buffer.get(), header->Size, &bytesReturned, nullptr))
{
auto deviceDescriptor = reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(buffer.get());
AZ_Printf("Streamer",
"Drive info for '%s':\n"
" Id: %s%s%s%s%s\n",
driveName,
deviceDescriptor->VendorIdOffset != 0 ? buffer.get() + deviceDescriptor->VendorIdOffset : "",
deviceDescriptor->VendorIdOffset != 0 ? " " : "",
deviceDescriptor->ProductIdOffset != 0 ? buffer.get() + deviceDescriptor->ProductIdOffset : "",
deviceDescriptor->ProductIdOffset != 0 ? " " : "",
deviceDescriptor->ProductRevisionOffset != 0 ? buffer.get() + deviceDescriptor->ProductRevisionOffset : "");
if (reportHardware)
{
auto deviceDescriptor = reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(buffer.get());
AZ_Printf("Streamer",
"Drive info for '%s':\n"
" Id: %s%s%s%s%s\n",
driveName,
deviceDescriptor->VendorIdOffset != 0 ? buffer.get() + deviceDescriptor->VendorIdOffset : "",
deviceDescriptor->VendorIdOffset != 0 ? " " : "",
deviceDescriptor->ProductIdOffset != 0 ? buffer.get() + deviceDescriptor->ProductIdOffset : "",
deviceDescriptor->ProductIdOffset != 0 ? " " : "",
deviceDescriptor->ProductRevisionOffset != 0 ? buffer.get() + deviceDescriptor->ProductRevisionOffset : "");
}
}
}
}
static void CollectDriveIoCapability(HANDLE deviceHandle, DriveInformation& information)
static void CollectDriveIoCapability(HANDLE deviceHandle, DriveInformation& information, bool reportHardware)
{
STORAGE_DEVICE_IO_CAPABILITY_DESCRIPTOR capabilityDescriptor{};
STORAGE_PROPERTY_QUERY query{};
@@ -180,15 +197,19 @@ namespace AZ::IO
&capabilityDescriptor, sizeof(capabilityDescriptor), &bytesReturned, nullptr))
{
information.m_ioChannelCount = aznumeric_caster(capabilityDescriptor.LunMaxIoCount);
AZ_Printf("Streamer",
" Max IO count (LUN): %i\n"
" Max IO count (Adapter): %i\n",
capabilityDescriptor.LunMaxIoCount,
capabilityDescriptor.AdapterMaxIoCount);
if (reportHardware)
{
AZ_Printf(
"Streamer",
" Max IO count (LUN): %i\n"
" Max IO count (Adapter): %i\n",
capabilityDescriptor.LunMaxIoCount,
capabilityDescriptor.AdapterMaxIoCount);
}
}
}
static void CollectDriveSeekPenalty(HANDLE deviceHandle, DriveInformation& information)
static void CollectDriveSeekPenalty(HANDLE deviceHandle, DriveInformation& information, bool reportHardware)
{
DWORD bytesReturned = 0;
@@ -201,9 +222,12 @@ namespace AZ::IO
&seekPenaltyDescriptor, sizeof(seekPenaltyDescriptor), &bytesReturned, nullptr))
{
information.m_hasSeekPenalty = seekPenaltyDescriptor.IncursSeekPenalty ? true : false;
AZ_Printf("Streamer",
" Has seek penalty: %s\n",
information.m_hasSeekPenalty ? "Yes" : "No");
if (reportHardware)
{
AZ_Printf("Streamer",
" Has seek penalty: %s\n",
information.m_hasSeekPenalty ? "Yes" : "No");
}
}
}
@@ -267,7 +291,7 @@ namespace AZ::IO
return visitor.m_found;
}
static bool CollectHardwareInfo(HardwareInformation& hardwareInfo, bool addAllDrives)
static bool CollectHardwareInfo(HardwareInformation& hardwareInfo, bool addAllDrives, bool reportHardware)
{
char drives[512];
if (::GetLogicalDriveStrings(sizeof(drives) - 1, drives))
@@ -286,7 +310,10 @@ namespace AZ::IO
{
if (!addAllDrives && !IsDriveUsed(driveIt))
{
AZ_Printf("Streamer", "Skipping drive '%s' because to no paths make use of it.\n", driveIt);
if (reportHardware)
{
AZ_Printf("Streamer", "Skipping drive '%s' because to no paths make use of it.\n", driveIt);
}
while (*driveIt++);
continue;
}
@@ -311,14 +338,14 @@ namespace AZ::IO
DriveInformation driveInformation;
driveInformation.m_paths.emplace_back(driveIt);
CollectIoAdaptor(deviceHandle, driveInformation, driveIt);
CollectIoAdaptor(deviceHandle, driveInformation, driveIt, reportHardware);
if (driveInformation.m_supportsQueuing)
{
CollectDriveInfo(deviceHandle, driveIt);
AppendDriveTypeToProfile(deviceHandle, driveInformation);
CollectDriveIoCapability(deviceHandle, driveInformation);
CollectDriveSeekPenalty(deviceHandle, driveInformation);
CollectAlignmentRequirements(deviceHandle, driveInformation);
CollectDriveInfo(deviceHandle, driveIt, reportHardware);
AppendDriveTypeToProfile(deviceHandle, driveInformation, reportHardware);
CollectDriveIoCapability(deviceHandle, driveInformation, reportHardware);
CollectDriveSeekPenalty(deviceHandle, driveInformation, reportHardware);
CollectAlignmentRequirements(deviceHandle, driveInformation, reportHardware);
hardwareInfo.m_maxPhysicalSectorSize =
AZStd::max(hardwareInfo.m_maxPhysicalSectorSize, driveInformation.m_physicalSectorSize);
@@ -329,24 +356,39 @@ namespace AZ::IO
driveMappings.insert({ storageDeviceNumber.DeviceNumber, AZStd::move(driveInformation) });
AZ_Printf("Streamer", "\n");
if (reportHardware)
{
AZ_Printf("Streamer", "\n");
}
}
else
{
AZ_Printf("Streamer", "Skipping drive '%s' because device does not support queuing requests.\n", driveIt);
if (reportHardware)
{
AZ_Printf(
"Streamer", "Skipping drive '%s' because device does not support queuing requests.\n", driveIt);
}
}
}
else
{
AZ_Printf("Streamer", "Drive '%s' is on the same storage drive as '%s'.\n",
driveIt, driveInformationEntry->second.m_paths[0].c_str());
if (reportHardware)
{
AZ_Printf(
"Streamer", "Drive '%s' is on the same storage drive as '%s'.\n",
driveIt, driveInformationEntry->second.m_paths[0].c_str());
}
driveInformationEntry->second.m_paths.emplace_back(driveIt);
}
}
else
{
AZ_Printf("Streamer",
"Skipping drive '%s' because device is not registered with OS as a storage device.\n", driveIt);
if (reportHardware)
{
AZ_Printf(
"Streamer", "Skipping drive '%s' because device is not registered with OS as a storage device.\n",
driveIt);
}
}
::CloseHandle(deviceHandle);
}
@@ -358,7 +400,10 @@ namespace AZ::IO
}
else
{
AZ_Printf("Streamer", "Skipping drive '%s', as it the type of drive is not supported.\n", driveIt);
if (reportHardware)
{
AZ_Printf("Streamer", "Skipping drive '%s', as it the type of drive is not supported.\n", driveIt);
}
}
// Move to next drive string. GetLogicalDriveStrings fills the target buffer with null-terminated strings, for instance
@@ -384,9 +429,9 @@ namespace AZ::IO
}
}
bool CollectIoHardwareInformation(HardwareInformation& info, bool includeAllHardware)
bool CollectIoHardwareInformation(HardwareInformation& info, bool includeAllHardware, bool reportHardware)
{
if (!CollectHardwareInfo(info, includeAllHardware))
if (!CollectHardwareInfo(info, includeAllHardware, reportHardware))
{
// The numbers below are based on common defaults from a local hardware survey.
info.m_maxPageSize = 4096;
@@ -22,20 +22,18 @@ namespace AZ::Utils
::MessageBox(0, message, title, MB_OK | MB_ICONERROR);
}
AZ::IO::FixedMaxPathString GetEngineManifestPath()
AZ::IO::FixedMaxPathString GetO3deManifestDirectory()
{
char userProfileBuffer[AZ::IO::MaxPathLength] = {0};
char userProfileBuffer[AZ::IO::MaxPathLength]{};
size_t variableSize = 0;
auto err = getenv_s(&variableSize, userProfileBuffer, AZ::IO::MaxPathLength, "USERPROFILE");
if (!err)
{
AZ::IO::FixedMaxPath path{userProfileBuffer};
AZ::IO::FixedMaxPath path{ userProfileBuffer };
path /= ".o3de";
path /= "o3de_manifest.json";
return path.Native();
}
return {};
}
} // namespace AZ::Utils
@@ -41,7 +41,7 @@ namespace AZ::Utils
const char* src = [appSupportDir UTF8String];
const size_t srcLen = strlen(src);
if (srcLen > MaxPathLength - 1)
if (srcLen > AZ::IO::MaxPathLength - 1)
{
return AZStd::nullopt;
}