mirror of
https://github.com/citra-mirror/citra.git
synced 2024-09-03 10:07:26 +02:00
Merge pull request #6023 from Morph1984/c4267
general: Enforce C4267 warning on MSVC
This commit is contained in:
commit
6f6a9357c2
@ -33,7 +33,6 @@ if (MSVC)
|
|||||||
# /Zc:throwingNew - Let codegen assume `operator new` (without std::nothrow) will never return null
|
# /Zc:throwingNew - Let codegen assume `operator new` (without std::nothrow) will never return null
|
||||||
# /external:* - Suppress warnings from external headers
|
# /external:* - Suppress warnings from external headers
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
/W3
|
|
||||||
/MP
|
/MP
|
||||||
/permissive-
|
/permissive-
|
||||||
/EHsc
|
/EHsc
|
||||||
@ -45,6 +44,10 @@ if (MSVC)
|
|||||||
/external:I "${CMAKE_SOURCE_DIR}/externals"
|
/external:I "${CMAKE_SOURCE_DIR}/externals"
|
||||||
/external:anglebrackets
|
/external:anglebrackets
|
||||||
/external:W0
|
/external:W0
|
||||||
|
|
||||||
|
# Warnings
|
||||||
|
/W3
|
||||||
|
/we4267 # 'var': conversion from 'size_t' to 'type', possible loss of data
|
||||||
)
|
)
|
||||||
|
|
||||||
# Since MSVC's debugging information is not very deterministic, so we have to disable it
|
# Since MSVC's debugging information is not very deterministic, so we have to disable it
|
||||||
|
@ -48,10 +48,11 @@ CheatDialog::~CheatDialog() = default;
|
|||||||
|
|
||||||
void CheatDialog::LoadCheats() {
|
void CheatDialog::LoadCheats() {
|
||||||
cheats = Core::System::GetInstance().CheatEngine().GetCheats();
|
cheats = Core::System::GetInstance().CheatEngine().GetCheats();
|
||||||
|
const int cheats_count = static_cast<int>(cheats.size());
|
||||||
|
|
||||||
ui->tableCheats->setRowCount(cheats.size());
|
ui->tableCheats->setRowCount(cheats_count);
|
||||||
|
|
||||||
for (size_t i = 0; i < cheats.size(); i++) {
|
for (int i = 0; i < cheats_count; i++) {
|
||||||
QCheckBox* enabled = new QCheckBox();
|
QCheckBox* enabled = new QCheckBox();
|
||||||
enabled->setChecked(cheats[i]->IsEnabled());
|
enabled->setChecked(cheats[i]->IsEnabled());
|
||||||
enabled->setStyleSheet(QStringLiteral("margin-left:7px;"));
|
enabled->setStyleSheet(QStringLiteral("margin-left:7px;"));
|
||||||
|
@ -950,14 +950,14 @@ void Config::SaveMultiplayerValues() {
|
|||||||
// Write ban list
|
// Write ban list
|
||||||
qt_config->beginWriteArray(QStringLiteral("username_ban_list"));
|
qt_config->beginWriteArray(QStringLiteral("username_ban_list"));
|
||||||
for (std::size_t i = 0; i < UISettings::values.ban_list.first.size(); ++i) {
|
for (std::size_t i = 0; i < UISettings::values.ban_list.first.size(); ++i) {
|
||||||
qt_config->setArrayIndex(i);
|
qt_config->setArrayIndex(static_cast<int>(i));
|
||||||
WriteSetting(QStringLiteral("username"),
|
WriteSetting(QStringLiteral("username"),
|
||||||
QString::fromStdString(UISettings::values.ban_list.first[i]));
|
QString::fromStdString(UISettings::values.ban_list.first[i]));
|
||||||
}
|
}
|
||||||
qt_config->endArray();
|
qt_config->endArray();
|
||||||
qt_config->beginWriteArray(QStringLiteral("ip_ban_list"));
|
qt_config->beginWriteArray(QStringLiteral("ip_ban_list"));
|
||||||
for (std::size_t i = 0; i < UISettings::values.ban_list.second.size(); ++i) {
|
for (std::size_t i = 0; i < UISettings::values.ban_list.second.size(); ++i) {
|
||||||
qt_config->setArrayIndex(i);
|
qt_config->setArrayIndex(static_cast<int>(i));
|
||||||
WriteSetting(QStringLiteral("ip"),
|
WriteSetting(QStringLiteral("ip"),
|
||||||
QString::fromStdString(UISettings::values.ban_list.second[i]));
|
QString::fromStdString(UISettings::values.ban_list.second[i]));
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,7 @@ void ConfigureCamera::SetConfiguration() {
|
|||||||
int index = GetSelectedCameraIndex();
|
int index = GetSelectedCameraIndex();
|
||||||
for (std::size_t i = 0; i < Implementations.size(); i++) {
|
for (std::size_t i = 0; i < Implementations.size(); i++) {
|
||||||
if (Implementations[i] == camera_name[index]) {
|
if (Implementations[i] == camera_name[index]) {
|
||||||
ui->image_source->setCurrentIndex(i);
|
ui->image_source->setCurrentIndex(static_cast<int>(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (camera_name[index] == "image") {
|
if (camera_name[index] == "image") {
|
||||||
|
@ -115,7 +115,7 @@ void IPCRecorderWidget::SetEnabled(bool enabled) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IPCRecorderWidget::Clear() {
|
void IPCRecorderWidget::Clear() {
|
||||||
id_offset += records.size();
|
id_offset += static_cast<int>(records.size());
|
||||||
|
|
||||||
records.clear();
|
records.clear();
|
||||||
ui->main->invisibleRootItem()->takeChildren();
|
ui->main->invisibleRootItem()->takeChildren();
|
||||||
|
@ -390,7 +390,7 @@ void ChatRoom::SetPlayerList(const Network::RoomMember::MemberList& member_list)
|
|||||||
return;
|
return;
|
||||||
QPixmap pixmap;
|
QPixmap pixmap;
|
||||||
if (!pixmap.loadFromData(reinterpret_cast<const u8*>(result.data()),
|
if (!pixmap.loadFromData(reinterpret_cast<const u8*>(result.data()),
|
||||||
result.size()))
|
static_cast<u32>(result.size())))
|
||||||
return;
|
return;
|
||||||
icon_cache[avatar_url] =
|
icon_cache[avatar_url] =
|
||||||
pixmap.scaled(48, 48, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
pixmap.scaled(48, 48, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||||
|
@ -10,7 +10,7 @@ namespace Common {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] constexpr T AlignUp(T value, std::size_t size) {
|
[[nodiscard]] constexpr T AlignUp(T value, std::size_t size) {
|
||||||
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
|
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
|
||||||
auto mod{value % size};
|
auto mod{static_cast<T>(value % size)};
|
||||||
value -= mod;
|
value -= mod;
|
||||||
return static_cast<T>(mod == T{0} ? value : value + size);
|
return static_cast<T>(mod == T{0} ? value : value + size);
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,10 @@
|
|||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
void FlipRGBA8Texture(std::vector<u8>& tex, u64 width, u64 height) {
|
void FlipRGBA8Texture(std::vector<u8>& tex, u32 width, u32 height) {
|
||||||
ASSERT(tex.size() == width * height * 4);
|
ASSERT(tex.size() == width * height * 4);
|
||||||
const u64 line_size = width * 4;
|
const u32 line_size = width * 4;
|
||||||
for (u64 line = 0; line < height / 2; line++) {
|
for (u32 line = 0; line < height / 2; line++) {
|
||||||
const u32 offset_1 = line * line_size;
|
const u32 offset_1 = line * line_size;
|
||||||
const u32 offset_2 = (height - line - 1) * line_size;
|
const u32 offset_2 = (height - line - 1) * line_size;
|
||||||
// Swap lines
|
// Swap lines
|
||||||
|
@ -8,5 +8,5 @@
|
|||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
void FlipRGBA8Texture(std::vector<u8>& tex, u64 width, u64 height);
|
void FlipRGBA8Texture(std::vector<u8>& tex, u32 width, u32 height);
|
||||||
}
|
}
|
||||||
|
@ -137,24 +137,4 @@ std::string Timer::GetTimeFormatted() {
|
|||||||
return fmt::format("{}:{:03}", tmp, milliseconds);
|
return fmt::format("{}:{:03}", tmp, milliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a timestamp with decimals for precise time comparisons
|
|
||||||
// ----------------
|
|
||||||
double Timer::GetDoubleTime() {
|
|
||||||
// Get continuous timestamp
|
|
||||||
u64 TmpSeconds = static_cast<u64>(Common::Timer::GetTimeSinceJan1970().count());
|
|
||||||
double ms = static_cast<u64>(GetTimeMs().count()) % 1000;
|
|
||||||
|
|
||||||
// Remove a few years. We only really want enough seconds to make
|
|
||||||
// sure that we are detecting actual actions, perhaps 60 seconds is
|
|
||||||
// enough really, but I leave a year of seconds anyway, in case the
|
|
||||||
// user's clock is incorrect or something like that.
|
|
||||||
TmpSeconds = TmpSeconds - (38 * 365 * 24 * 60 * 60);
|
|
||||||
|
|
||||||
// Make a smaller integer that fits in the double
|
|
||||||
u32 Seconds = static_cast<u32>(TmpSeconds);
|
|
||||||
double TmpTime = Seconds + ms;
|
|
||||||
|
|
||||||
return TmpTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // Namespace Common
|
} // Namespace Common
|
||||||
|
@ -24,7 +24,6 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] static std::chrono::seconds GetTimeSinceJan1970();
|
[[nodiscard]] static std::chrono::seconds GetTimeSinceJan1970();
|
||||||
[[nodiscard]] static std::chrono::seconds GetLocalTimeSinceJan1970();
|
[[nodiscard]] static std::chrono::seconds GetLocalTimeSinceJan1970();
|
||||||
[[nodiscard]] static double GetDoubleTime();
|
|
||||||
|
|
||||||
[[nodiscard]] static std::string GetTimeFormatted();
|
[[nodiscard]] static std::string GetTimeFormatted();
|
||||||
[[nodiscard]] std::string GetTimeElapsedFormatted() const;
|
[[nodiscard]] std::string GetTimeElapsedFormatted() const;
|
||||||
|
@ -158,10 +158,10 @@ struct ABIFrameInfo {
|
|||||||
|
|
||||||
inline ABIFrameInfo ABI_CalculateFrameSize(std::bitset<32> regs, std::size_t rsp_alignment,
|
inline ABIFrameInfo ABI_CalculateFrameSize(std::bitset<32> regs, std::size_t rsp_alignment,
|
||||||
std::size_t needed_frame_size) {
|
std::size_t needed_frame_size) {
|
||||||
int count = (regs & ABI_ALL_GPRS).count();
|
const auto count = (regs & ABI_ALL_GPRS).count();
|
||||||
rsp_alignment -= count * 8;
|
rsp_alignment -= count * 8;
|
||||||
std::size_t subtraction = 0;
|
std::size_t subtraction = 0;
|
||||||
int xmm_count = (regs & ABI_ALL_XMMS).count();
|
const auto xmm_count = (regs & ABI_ALL_XMMS).count();
|
||||||
if (xmm_count) {
|
if (xmm_count) {
|
||||||
// If we have any XMMs to save, we must align the stack here.
|
// If we have any XMMs to save, we must align the stack here.
|
||||||
subtraction = rsp_alignment & 0xF;
|
subtraction = rsp_alignment & 0xF;
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
namespace VideoDumper {
|
namespace VideoDumper {
|
||||||
|
|
||||||
VideoFrame::VideoFrame(std::size_t width_, std::size_t height_, u8* data_)
|
VideoFrame::VideoFrame(std::size_t width_, std::size_t height_, u8* data_)
|
||||||
: width(width_), height(height_), stride(width * 4), data(data_, data_ + width * height * 4) {}
|
: width(width_), height(height_), stride(static_cast<u32>(width * 4)),
|
||||||
|
data(data_, data_ + width * height * 4) {}
|
||||||
|
|
||||||
Backend::~Backend() = default;
|
Backend::~Backend() = default;
|
||||||
NullBackend::~NullBackend() = default;
|
NullBackend::~NullBackend() = default;
|
||||||
|
@ -354,7 +354,7 @@ void FFmpegAudioStream::ProcessFrame(const VariableAudioFrame& channel0,
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto resampled_count = swr_convert(swr_context.get(), dst_data.data(), frame_size - offset,
|
auto resampled_count = swr_convert(swr_context.get(), dst_data.data(), frame_size - offset,
|
||||||
src_data.data(), channel0.size());
|
src_data.data(), static_cast<int>(channel0.size()));
|
||||||
if (resampled_count < 0) {
|
if (resampled_count < 0) {
|
||||||
LOG_ERROR(Render, "Audio frame dropped: Could not resample data");
|
LOG_ERROR(Render, "Audio frame dropped: Could not resample data");
|
||||||
return;
|
return;
|
||||||
|
@ -143,7 +143,7 @@ u32 GetSeedCount() {
|
|||||||
if (!db.Load()) {
|
if (!db.Load()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return db.GetCount();
|
return static_cast<u32>(db.GetCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
@ -209,7 +209,8 @@ ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySy
|
|||||||
target_address =
|
target_address =
|
||||||
dst_process->vm_manager
|
dst_process->vm_manager
|
||||||
.MapBackingMemoryToBase(Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE,
|
.MapBackingMemoryToBase(Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE,
|
||||||
buffer, buffer->GetSize(), Kernel::MemoryState::Shared)
|
buffer, static_cast<u32>(buffer->GetSize()),
|
||||||
|
Kernel::MemoryState::Shared)
|
||||||
.Unwrap();
|
.Unwrap();
|
||||||
|
|
||||||
cmd_buf[i++] = target_address + page_offset;
|
cmd_buf[i++] = target_address + page_offset;
|
||||||
@ -217,7 +218,7 @@ ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySy
|
|||||||
// Reserve a page of memory after the mapped buffer
|
// Reserve a page of memory after the mapped buffer
|
||||||
dst_process->vm_manager.MapBackingMemoryToBase(
|
dst_process->vm_manager.MapBackingMemoryToBase(
|
||||||
Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer,
|
Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer,
|
||||||
reserve_buffer->GetSize(), Kernel::MemoryState::Reserved);
|
static_cast<u32>(reserve_buffer->GetSize()), Kernel::MemoryState::Reserved);
|
||||||
|
|
||||||
mapped_buffer_context.push_back({permissions, size, source_address,
|
mapped_buffer_context.push_back({permissions, size, source_address,
|
||||||
target_address + page_offset, std::move(buffer),
|
target_address + page_offset, std::move(buffer),
|
||||||
|
@ -389,15 +389,16 @@ ResultVal<std::shared_ptr<Thread>> KernelSystem::CreateThread(
|
|||||||
auto& vm_manager = owner_process->vm_manager;
|
auto& vm_manager = owner_process->vm_manager;
|
||||||
|
|
||||||
// Map the page to the current process' address space.
|
// Map the page to the current process' address space.
|
||||||
vm_manager.MapBackingMemory(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE,
|
vm_manager.MapBackingMemory(
|
||||||
memory.GetFCRAMRef(*offset), Memory::PAGE_SIZE,
|
Memory::TLS_AREA_VADDR + static_cast<VAddr>(available_page) * Memory::PAGE_SIZE,
|
||||||
MemoryState::Locked);
|
memory.GetFCRAMRef(*offset), Memory::PAGE_SIZE, MemoryState::Locked);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark the slot as used
|
// Mark the slot as used
|
||||||
tls_slots[available_page].set(available_slot);
|
tls_slots[available_page].set(available_slot);
|
||||||
thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE +
|
thread->tls_address = Memory::TLS_AREA_VADDR +
|
||||||
available_slot * Memory::TLS_ENTRY_SIZE;
|
static_cast<VAddr>(available_page) * Memory::PAGE_SIZE +
|
||||||
|
static_cast<VAddr>(available_slot) * Memory::TLS_ENTRY_SIZE;
|
||||||
|
|
||||||
memory.ZeroBlock(*owner_process, thread->tls_address, Memory::TLS_ENTRY_SIZE);
|
memory.ZeroBlock(*owner_process, thread->tls_address, Memory::TLS_ENTRY_SIZE);
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ void DSP_DSP::ReadPipeIfPossible(Kernel::HLERequestContext& ctx) {
|
|||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 2);
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 2);
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
rb.Push<u16>(pipe_buffer.size());
|
rb.Push<u16>(static_cast<u16>(pipe_buffer.size()));
|
||||||
rb.PushStaticBuffer(std::move(pipe_buffer), 0);
|
rb.PushStaticBuffer(std::move(pipe_buffer), 0);
|
||||||
|
|
||||||
LOG_DEBUG(Service_DSP, "channel={}, peer={}, size=0x{:04X}, pipe_readable_size=0x{:04X}",
|
LOG_DEBUG(Service_DSP, "channel={}, peer={}, size=0x{:04X}, pipe_readable_size=0x{:04X}",
|
||||||
|
@ -141,7 +141,7 @@ void Module::Interface::GetTagInfo(Kernel::HLERequestContext& ctx) {
|
|||||||
|
|
||||||
TagInfo tag_info{};
|
TagInfo tag_info{};
|
||||||
tag_info.uuid = nfc->amiibo_data.uuid;
|
tag_info.uuid = nfc->amiibo_data.uuid;
|
||||||
tag_info.id_offset_size = tag_info.uuid.size();
|
tag_info.id_offset_size = static_cast<u16>(tag_info.uuid.size());
|
||||||
tag_info.unk1 = 0x0;
|
tag_info.unk1 = 0x0;
|
||||||
tag_info.unk2 = 0x2;
|
tag_info.unk2 = 0x2;
|
||||||
|
|
||||||
|
@ -335,7 +335,8 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_
|
|||||||
}
|
}
|
||||||
// There is no SDLJoystick without a mapped SDL_Joystick
|
// There is no SDLJoystick without a mapped SDL_Joystick
|
||||||
// Create a new SDLJoystick
|
// Create a new SDLJoystick
|
||||||
auto joystick = std::make_shared<SDLJoystick>(guid, map_it->second.size(), sdl_joystick);
|
auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(map_it->second.size()),
|
||||||
|
sdl_joystick);
|
||||||
return map_it->second.emplace_back(std::move(joystick));
|
return map_it->second.emplace_back(std::move(joystick));
|
||||||
}
|
}
|
||||||
auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick);
|
auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick);
|
||||||
@ -483,7 +484,8 @@ void SDLState::InitJoystick(int joystick_index) {
|
|||||||
(*it)->SetSDLJoystick(sdl_joystick);
|
(*it)->SetSDLJoystick(sdl_joystick);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto joystick = std::make_shared<SDLJoystick>(guid, joystick_guid_list.size(), sdl_joystick);
|
auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(joystick_guid_list.size()),
|
||||||
|
sdl_joystick);
|
||||||
joystick_guid_list.emplace_back(std::move(joystick));
|
joystick_guid_list.emplace_back(std::move(joystick));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,8 +521,8 @@ void SDLState::InitGameController(int controller_index) {
|
|||||||
(*it)->SetSDLGameController(sdl_controller);
|
(*it)->SetSDLGameController(sdl_controller);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto controller =
|
auto controller = std::make_shared<SDLGameController>(
|
||||||
std::make_shared<SDLGameController>(guid, controller_guid_list.size(), sdl_controller);
|
guid, static_cast<int>(controller_guid_list.size()), sdl_controller);
|
||||||
controller_guid_list.emplace_back(std::move(controller));
|
controller_guid_list.emplace_back(std::move(controller));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,8 +142,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
|
|||||||
std::fill(buffer.GetPtr(), buffer.GetPtr() + buffer.GetSize(), 0xAB);
|
std::fill(buffer.GetPtr(), buffer.GetPtr() + buffer.GetSize(), 0xAB);
|
||||||
|
|
||||||
VAddr target_address = 0x10000000;
|
VAddr target_address = 0x10000000;
|
||||||
auto result = process->vm_manager.MapBackingMemory(target_address, buffer, buffer.GetSize(),
|
auto result = process->vm_manager.MapBackingMemory(
|
||||||
MemoryState::Private);
|
target_address, buffer, static_cast<u32>(buffer.GetSize()), MemoryState::Private);
|
||||||
REQUIRE(result.Code() == RESULT_SUCCESS);
|
REQUIRE(result.Code() == RESULT_SUCCESS);
|
||||||
|
|
||||||
const u32_le input[]{
|
const u32_le input[]{
|
||||||
@ -156,7 +156,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
|
|||||||
|
|
||||||
CHECK(context.GetStaticBuffer(0) == mem->Vector());
|
CHECK(context.GetStaticBuffer(0) == mem->Vector());
|
||||||
|
|
||||||
REQUIRE(process->vm_manager.UnmapRange(target_address, buffer.GetSize()) == RESULT_SUCCESS);
|
REQUIRE(process->vm_manager.UnmapRange(
|
||||||
|
target_address, static_cast<u32>(buffer.GetSize())) == RESULT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("translates MappedBuffer descriptors") {
|
SECTION("translates MappedBuffer descriptors") {
|
||||||
@ -165,8 +166,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
|
|||||||
std::fill(buffer.GetPtr(), buffer.GetPtr() + buffer.GetSize(), 0xCD);
|
std::fill(buffer.GetPtr(), buffer.GetPtr() + buffer.GetSize(), 0xCD);
|
||||||
|
|
||||||
VAddr target_address = 0x10000000;
|
VAddr target_address = 0x10000000;
|
||||||
auto result = process->vm_manager.MapBackingMemory(target_address, buffer, buffer.GetSize(),
|
auto result = process->vm_manager.MapBackingMemory(
|
||||||
MemoryState::Private);
|
target_address, buffer, static_cast<u32>(buffer.GetSize()), MemoryState::Private);
|
||||||
|
|
||||||
const u32_le input[]{
|
const u32_le input[]{
|
||||||
IPC::MakeHeader(0, 0, 2),
|
IPC::MakeHeader(0, 0, 2),
|
||||||
@ -181,7 +182,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
|
|||||||
|
|
||||||
CHECK(other_buffer == mem->Vector());
|
CHECK(other_buffer == mem->Vector());
|
||||||
|
|
||||||
REQUIRE(process->vm_manager.UnmapRange(target_address, buffer.GetSize()) == RESULT_SUCCESS);
|
REQUIRE(process->vm_manager.UnmapRange(
|
||||||
|
target_address, static_cast<u32>(buffer.GetSize())) == RESULT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("translates mixed params") {
|
SECTION("translates mixed params") {
|
||||||
@ -195,12 +197,14 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
|
|||||||
|
|
||||||
VAddr target_address_static = 0x10000000;
|
VAddr target_address_static = 0x10000000;
|
||||||
auto result = process->vm_manager.MapBackingMemory(
|
auto result = process->vm_manager.MapBackingMemory(
|
||||||
target_address_static, buffer_static, buffer_static.GetSize(), MemoryState::Private);
|
target_address_static, buffer_static, static_cast<u32>(buffer_static.GetSize()),
|
||||||
|
MemoryState::Private);
|
||||||
REQUIRE(result.Code() == RESULT_SUCCESS);
|
REQUIRE(result.Code() == RESULT_SUCCESS);
|
||||||
|
|
||||||
VAddr target_address_mapped = 0x20000000;
|
VAddr target_address_mapped = 0x20000000;
|
||||||
result = process->vm_manager.MapBackingMemory(
|
result = process->vm_manager.MapBackingMemory(target_address_mapped, buffer_mapped,
|
||||||
target_address_mapped, buffer_mapped, buffer_mapped.GetSize(), MemoryState::Private);
|
static_cast<u32>(buffer_mapped.GetSize()),
|
||||||
|
MemoryState::Private);
|
||||||
REQUIRE(result.Code() == RESULT_SUCCESS);
|
REQUIRE(result.Code() == RESULT_SUCCESS);
|
||||||
|
|
||||||
auto a = MakeObject(kernel);
|
auto a = MakeObject(kernel);
|
||||||
@ -230,9 +234,11 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
|
|||||||
context.GetMappedBuffer(0).Read(other_buffer.data(), 0, buffer_mapped.GetSize());
|
context.GetMappedBuffer(0).Read(other_buffer.data(), 0, buffer_mapped.GetSize());
|
||||||
CHECK(other_buffer == mem_mapped->Vector());
|
CHECK(other_buffer == mem_mapped->Vector());
|
||||||
|
|
||||||
REQUIRE(process->vm_manager.UnmapRange(target_address_static, buffer_static.GetSize()) ==
|
REQUIRE(process->vm_manager.UnmapRange(target_address_static,
|
||||||
|
static_cast<u32>(buffer_static.GetSize())) ==
|
||||||
RESULT_SUCCESS);
|
RESULT_SUCCESS);
|
||||||
REQUIRE(process->vm_manager.UnmapRange(target_address_mapped, buffer_mapped.GetSize()) ==
|
REQUIRE(process->vm_manager.UnmapRange(target_address_mapped,
|
||||||
|
static_cast<u32>(buffer_mapped.GetSize())) ==
|
||||||
RESULT_SUCCESS);
|
RESULT_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,7 +331,8 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
|
|||||||
|
|
||||||
VAddr target_address = 0x10000000;
|
VAddr target_address = 0x10000000;
|
||||||
auto result = process->vm_manager.MapBackingMemory(
|
auto result = process->vm_manager.MapBackingMemory(
|
||||||
target_address, output_buffer, output_buffer.GetSize(), MemoryState::Private);
|
target_address, output_buffer, static_cast<u32>(output_buffer.GetSize()),
|
||||||
|
MemoryState::Private);
|
||||||
REQUIRE(result.Code() == RESULT_SUCCESS);
|
REQUIRE(result.Code() == RESULT_SUCCESS);
|
||||||
|
|
||||||
input[0] = IPC::MakeHeader(0, 0, 2);
|
input[0] = IPC::MakeHeader(0, 0, 2);
|
||||||
@ -343,8 +350,8 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
|
|||||||
context.WriteToOutgoingCommandBuffer(output_cmdbuff.data(), *process);
|
context.WriteToOutgoingCommandBuffer(output_cmdbuff.data(), *process);
|
||||||
|
|
||||||
CHECK(output_mem->Vector() == input_buffer);
|
CHECK(output_mem->Vector() == input_buffer);
|
||||||
REQUIRE(process->vm_manager.UnmapRange(target_address, output_buffer.GetSize()) ==
|
REQUIRE(process->vm_manager.UnmapRange(
|
||||||
RESULT_SUCCESS);
|
target_address, static_cast<u32>(output_buffer.GetSize())) == RESULT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("translates StaticBuffer descriptors") {
|
SECTION("translates StaticBuffer descriptors") {
|
||||||
@ -356,7 +363,8 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
|
|||||||
|
|
||||||
VAddr target_address = 0x10000000;
|
VAddr target_address = 0x10000000;
|
||||||
auto result = process->vm_manager.MapBackingMemory(
|
auto result = process->vm_manager.MapBackingMemory(
|
||||||
target_address, output_buffer, output_buffer.GetSize(), MemoryState::Private);
|
target_address, output_buffer, static_cast<u32>(output_buffer.GetSize()),
|
||||||
|
MemoryState::Private);
|
||||||
REQUIRE(result.Code() == RESULT_SUCCESS);
|
REQUIRE(result.Code() == RESULT_SUCCESS);
|
||||||
|
|
||||||
const u32_le input_cmdbuff[]{
|
const u32_le input_cmdbuff[]{
|
||||||
@ -378,8 +386,8 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
|
|||||||
CHECK(output[1] == IPC::MappedBufferDesc(output_buffer.GetSize(), IPC::W));
|
CHECK(output[1] == IPC::MappedBufferDesc(output_buffer.GetSize(), IPC::W));
|
||||||
CHECK(output[2] == target_address);
|
CHECK(output[2] == target_address);
|
||||||
CHECK(output_mem->Vector() == input_buffer);
|
CHECK(output_mem->Vector() == input_buffer);
|
||||||
REQUIRE(process->vm_manager.UnmapRange(target_address, output_buffer.GetSize()) ==
|
REQUIRE(process->vm_manager.UnmapRange(
|
||||||
RESULT_SUCCESS);
|
target_address, static_cast<u32>(output_buffer.GetSize())) == RESULT_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,13 +16,14 @@ TEST_CASE("Memory Basics", "[kernel][memory]") {
|
|||||||
SECTION("mapping memory") {
|
SECTION("mapping memory") {
|
||||||
// Because of the PageTable, Kernel::VMManager is too big to be created on the stack.
|
// Because of the PageTable, Kernel::VMManager is too big to be created on the stack.
|
||||||
auto manager = std::make_unique<Kernel::VMManager>(memory);
|
auto manager = std::make_unique<Kernel::VMManager>(memory);
|
||||||
auto result = manager->MapBackingMemory(Memory::HEAP_VADDR, block, block.GetSize(),
|
auto result =
|
||||||
|
manager->MapBackingMemory(Memory::HEAP_VADDR, block, static_cast<u32>(block.GetSize()),
|
||||||
Kernel::MemoryState::Private);
|
Kernel::MemoryState::Private);
|
||||||
REQUIRE(result.Code() == RESULT_SUCCESS);
|
REQUIRE(result.Code() == RESULT_SUCCESS);
|
||||||
|
|
||||||
auto vma = manager->FindVMA(Memory::HEAP_VADDR);
|
auto vma = manager->FindVMA(Memory::HEAP_VADDR);
|
||||||
CHECK(vma != manager->vma_map.end());
|
CHECK(vma != manager->vma_map.end());
|
||||||
CHECK(vma->second.size == block.GetSize());
|
CHECK(vma->second.size == static_cast<u32>(block.GetSize()));
|
||||||
CHECK(vma->second.type == Kernel::VMAType::BackingMemory);
|
CHECK(vma->second.type == Kernel::VMAType::BackingMemory);
|
||||||
CHECK(vma->second.backing_memory.GetPtr() == block.GetPtr());
|
CHECK(vma->second.backing_memory.GetPtr() == block.GetPtr());
|
||||||
CHECK(vma->second.meminfo_state == Kernel::MemoryState::Private);
|
CHECK(vma->second.meminfo_state == Kernel::MemoryState::Private);
|
||||||
@ -31,11 +32,13 @@ TEST_CASE("Memory Basics", "[kernel][memory]") {
|
|||||||
SECTION("unmapping memory") {
|
SECTION("unmapping memory") {
|
||||||
// Because of the PageTable, Kernel::VMManager is too big to be created on the stack.
|
// Because of the PageTable, Kernel::VMManager is too big to be created on the stack.
|
||||||
auto manager = std::make_unique<Kernel::VMManager>(memory);
|
auto manager = std::make_unique<Kernel::VMManager>(memory);
|
||||||
auto result = manager->MapBackingMemory(Memory::HEAP_VADDR, block, block.GetSize(),
|
auto result =
|
||||||
|
manager->MapBackingMemory(Memory::HEAP_VADDR, block, static_cast<u32>(block.GetSize()),
|
||||||
Kernel::MemoryState::Private);
|
Kernel::MemoryState::Private);
|
||||||
REQUIRE(result.Code() == RESULT_SUCCESS);
|
REQUIRE(result.Code() == RESULT_SUCCESS);
|
||||||
|
|
||||||
ResultCode code = manager->UnmapRange(Memory::HEAP_VADDR, block.GetSize());
|
ResultCode code =
|
||||||
|
manager->UnmapRange(Memory::HEAP_VADDR, static_cast<u32>(block.GetSize()));
|
||||||
REQUIRE(code == RESULT_SUCCESS);
|
REQUIRE(code == RESULT_SUCCESS);
|
||||||
|
|
||||||
auto vma = manager->FindVMA(Memory::HEAP_VADDR);
|
auto vma = manager->FindVMA(Memory::HEAP_VADDR);
|
||||||
@ -47,36 +50,39 @@ TEST_CASE("Memory Basics", "[kernel][memory]") {
|
|||||||
SECTION("changing memory permissions") {
|
SECTION("changing memory permissions") {
|
||||||
// Because of the PageTable, Kernel::VMManager is too big to be created on the stack.
|
// Because of the PageTable, Kernel::VMManager is too big to be created on the stack.
|
||||||
auto manager = std::make_unique<Kernel::VMManager>(memory);
|
auto manager = std::make_unique<Kernel::VMManager>(memory);
|
||||||
auto result = manager->MapBackingMemory(Memory::HEAP_VADDR, block, block.GetSize(),
|
auto result =
|
||||||
|
manager->MapBackingMemory(Memory::HEAP_VADDR, block, static_cast<u32>(block.GetSize()),
|
||||||
Kernel::MemoryState::Private);
|
Kernel::MemoryState::Private);
|
||||||
REQUIRE(result.Code() == RESULT_SUCCESS);
|
REQUIRE(result.Code() == RESULT_SUCCESS);
|
||||||
|
|
||||||
ResultCode code = manager->ReprotectRange(Memory::HEAP_VADDR, block.GetSize(),
|
ResultCode code = manager->ReprotectRange(
|
||||||
Kernel::VMAPermission::Execute);
|
Memory::HEAP_VADDR, static_cast<u32>(block.GetSize()), Kernel::VMAPermission::Execute);
|
||||||
CHECK(code == RESULT_SUCCESS);
|
CHECK(code == RESULT_SUCCESS);
|
||||||
|
|
||||||
auto vma = manager->FindVMA(Memory::HEAP_VADDR);
|
auto vma = manager->FindVMA(Memory::HEAP_VADDR);
|
||||||
CHECK(vma != manager->vma_map.end());
|
CHECK(vma != manager->vma_map.end());
|
||||||
CHECK(vma->second.permissions == Kernel::VMAPermission::Execute);
|
CHECK(vma->second.permissions == Kernel::VMAPermission::Execute);
|
||||||
|
|
||||||
code = manager->UnmapRange(Memory::HEAP_VADDR, block.GetSize());
|
code = manager->UnmapRange(Memory::HEAP_VADDR, static_cast<u32>(block.GetSize()));
|
||||||
REQUIRE(code == RESULT_SUCCESS);
|
REQUIRE(code == RESULT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("changing memory state") {
|
SECTION("changing memory state") {
|
||||||
// Because of the PageTable, Kernel::VMManager is too big to be created on the stack.
|
// Because of the PageTable, Kernel::VMManager is too big to be created on the stack.
|
||||||
auto manager = std::make_unique<Kernel::VMManager>(memory);
|
auto manager = std::make_unique<Kernel::VMManager>(memory);
|
||||||
auto result = manager->MapBackingMemory(Memory::HEAP_VADDR, block, block.GetSize(),
|
auto result =
|
||||||
|
manager->MapBackingMemory(Memory::HEAP_VADDR, block, static_cast<u32>(block.GetSize()),
|
||||||
Kernel::MemoryState::Private);
|
Kernel::MemoryState::Private);
|
||||||
REQUIRE(result.Code() == RESULT_SUCCESS);
|
REQUIRE(result.Code() == RESULT_SUCCESS);
|
||||||
|
|
||||||
ResultCode code = manager->ReprotectRange(Memory::HEAP_VADDR, block.GetSize(),
|
ResultCode code =
|
||||||
|
manager->ReprotectRange(Memory::HEAP_VADDR, static_cast<u32>(block.GetSize()),
|
||||||
Kernel::VMAPermission::ReadWrite);
|
Kernel::VMAPermission::ReadWrite);
|
||||||
REQUIRE(code == RESULT_SUCCESS);
|
REQUIRE(code == RESULT_SUCCESS);
|
||||||
|
|
||||||
SECTION("with invalid address") {
|
SECTION("with invalid address") {
|
||||||
ResultCode code = manager->ChangeMemoryState(
|
ResultCode code = manager->ChangeMemoryState(
|
||||||
0xFFFFFFFF, block.GetSize(), Kernel::MemoryState::Locked,
|
0xFFFFFFFF, static_cast<u32>(block.GetSize()), Kernel::MemoryState::Locked,
|
||||||
Kernel::VMAPermission::ReadWrite, Kernel::MemoryState::Aliased,
|
Kernel::VMAPermission::ReadWrite, Kernel::MemoryState::Aliased,
|
||||||
Kernel::VMAPermission::Execute);
|
Kernel::VMAPermission::Execute);
|
||||||
CHECK(code == Kernel::ERR_INVALID_ADDRESS);
|
CHECK(code == Kernel::ERR_INVALID_ADDRESS);
|
||||||
@ -84,7 +90,7 @@ TEST_CASE("Memory Basics", "[kernel][memory]") {
|
|||||||
|
|
||||||
SECTION("ignoring the original permissions") {
|
SECTION("ignoring the original permissions") {
|
||||||
ResultCode code = manager->ChangeMemoryState(
|
ResultCode code = manager->ChangeMemoryState(
|
||||||
Memory::HEAP_VADDR, block.GetSize(), Kernel::MemoryState::Private,
|
Memory::HEAP_VADDR, static_cast<u32>(block.GetSize()), Kernel::MemoryState::Private,
|
||||||
Kernel::VMAPermission::None, Kernel::MemoryState::Locked,
|
Kernel::VMAPermission::None, Kernel::MemoryState::Locked,
|
||||||
Kernel::VMAPermission::Write);
|
Kernel::VMAPermission::Write);
|
||||||
CHECK(code == RESULT_SUCCESS);
|
CHECK(code == RESULT_SUCCESS);
|
||||||
@ -97,7 +103,7 @@ TEST_CASE("Memory Basics", "[kernel][memory]") {
|
|||||||
|
|
||||||
SECTION("enforcing the original permissions with correct expectations") {
|
SECTION("enforcing the original permissions with correct expectations") {
|
||||||
ResultCode code = manager->ChangeMemoryState(
|
ResultCode code = manager->ChangeMemoryState(
|
||||||
Memory::HEAP_VADDR, block.GetSize(), Kernel::MemoryState::Private,
|
Memory::HEAP_VADDR, static_cast<u32>(block.GetSize()), Kernel::MemoryState::Private,
|
||||||
Kernel::VMAPermission::ReadWrite, Kernel::MemoryState::Aliased,
|
Kernel::VMAPermission::ReadWrite, Kernel::MemoryState::Aliased,
|
||||||
Kernel::VMAPermission::Execute);
|
Kernel::VMAPermission::Execute);
|
||||||
CHECK(code == RESULT_SUCCESS);
|
CHECK(code == RESULT_SUCCESS);
|
||||||
@ -110,7 +116,7 @@ TEST_CASE("Memory Basics", "[kernel][memory]") {
|
|||||||
|
|
||||||
SECTION("with incorrect permission expectations") {
|
SECTION("with incorrect permission expectations") {
|
||||||
ResultCode code = manager->ChangeMemoryState(
|
ResultCode code = manager->ChangeMemoryState(
|
||||||
Memory::HEAP_VADDR, block.GetSize(), Kernel::MemoryState::Private,
|
Memory::HEAP_VADDR, static_cast<u32>(block.GetSize()), Kernel::MemoryState::Private,
|
||||||
Kernel::VMAPermission::Execute, Kernel::MemoryState::Aliased,
|
Kernel::VMAPermission::Execute, Kernel::MemoryState::Aliased,
|
||||||
Kernel::VMAPermission::Execute);
|
Kernel::VMAPermission::Execute);
|
||||||
CHECK(code == Kernel::ERR_INVALID_ADDRESS_STATE);
|
CHECK(code == Kernel::ERR_INVALID_ADDRESS_STATE);
|
||||||
@ -123,7 +129,7 @@ TEST_CASE("Memory Basics", "[kernel][memory]") {
|
|||||||
|
|
||||||
SECTION("with incorrect state expectations") {
|
SECTION("with incorrect state expectations") {
|
||||||
ResultCode code = manager->ChangeMemoryState(
|
ResultCode code = manager->ChangeMemoryState(
|
||||||
Memory::HEAP_VADDR, block.GetSize(), Kernel::MemoryState::Locked,
|
Memory::HEAP_VADDR, static_cast<u32>(block.GetSize()), Kernel::MemoryState::Locked,
|
||||||
Kernel::VMAPermission::ReadWrite, Kernel::MemoryState::Aliased,
|
Kernel::VMAPermission::ReadWrite, Kernel::MemoryState::Aliased,
|
||||||
Kernel::VMAPermission::Execute);
|
Kernel::VMAPermission::Execute);
|
||||||
CHECK(code == Kernel::ERR_INVALID_ADDRESS_STATE);
|
CHECK(code == Kernel::ERR_INVALID_ADDRESS_STATE);
|
||||||
@ -134,7 +140,7 @@ TEST_CASE("Memory Basics", "[kernel][memory]") {
|
|||||||
CHECK(vma->second.meminfo_state == Kernel::MemoryState::Private);
|
CHECK(vma->second.meminfo_state == Kernel::MemoryState::Private);
|
||||||
}
|
}
|
||||||
|
|
||||||
code = manager->UnmapRange(Memory::HEAP_VADDR, block.GetSize());
|
code = manager->UnmapRange(Memory::HEAP_VADDR, static_cast<u32>(block.GetSize()));
|
||||||
REQUIRE(code == RESULT_SUCCESS);
|
REQUIRE(code == RESULT_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -798,7 +798,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glBindTexture(GL_TEXTURE_2D, state.texture_units[0].texture_2d);
|
glBindTexture(GL_TEXTURE_2D, state.texture_units[0].texture_2d);
|
||||||
|
|
||||||
for (std::size_t level{0}; level <= color_surface->max_level; ++level) {
|
for (u32 level{0}; level <= color_surface->max_level; ++level) {
|
||||||
glCopyImageSubData(color_surface->texture.handle, GL_TEXTURE_2D, level, 0, 0, 0,
|
glCopyImageSubData(color_surface->texture.handle, GL_TEXTURE_2D, level, 0, 0, 0,
|
||||||
temp_tex.handle, GL_TEXTURE_2D, level, 0, 0, 0,
|
temp_tex.handle, GL_TEXTURE_2D, level, 0, 0, 0,
|
||||||
color_surface->GetScaledWidth() >> level,
|
color_surface->GetScaledWidth() >> level,
|
||||||
|
@ -50,16 +50,18 @@ void TextureDownloaderES::Test() {
|
|||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
original_data.resize(tex_size * tex_size);
|
original_data.resize(tex_size * tex_size);
|
||||||
for (std::size_t idx = 0; idx < original_data.size(); ++idx)
|
for (std::size_t idx = 0; idx < original_data.size(); ++idx) {
|
||||||
original_data[idx] = data_generator(idx);
|
original_data[idx] = data_generator(idx);
|
||||||
glTexStorage2D(GL_TEXTURE_2D, 1, tuple.internal_format, tex_size, tex_size);
|
}
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tex_size, tex_size, tuple.format, tuple.type,
|
GLsizei tex_sizei = static_cast<GLsizei>(tex_size);
|
||||||
|
glTexStorage2D(GL_TEXTURE_2D, 1, tuple.internal_format, tex_sizei, tex_sizei);
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tex_sizei, tex_sizei, tuple.format, tuple.type,
|
||||||
original_data.data());
|
original_data.data());
|
||||||
|
|
||||||
decltype(original_data) new_data(original_data.size());
|
decltype(original_data) new_data(original_data.size());
|
||||||
glFinish();
|
glFinish();
|
||||||
auto start = std::chrono::high_resolution_clock::now();
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
GetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type, tex_size, tex_size,
|
GetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type, tex_sizei, tex_sizei,
|
||||||
new_data.data());
|
new_data.data());
|
||||||
glFinish();
|
glFinish();
|
||||||
auto time = std::chrono::high_resolution_clock::now() - start;
|
auto time = std::chrono::high_resolution_clock::now() - start;
|
||||||
|
Loading…
Reference in New Issue
Block a user