Apply clang-format across the whole tree
Run clang-format (the repo's .clang-format: LLVM base, 120 cols, tabs, Allman functions) over every source file so the tree is formatter-clean. Whitespace only -- no behavior change; full x64 + x86 suites pass. Also set SortIncludes: false in .clang-format. Windows include order is load-bearing (windows.h must precede tlhelp32.h / mmreg.h / xinput.h / dinput.h; winsock2.h must precede windows.h), and the default alphabetical sort reorders tlhelp32.h ahead of windows.h -- a build break. Leaving order alone keeps the manual, correct grouping.
This commit is contained in:
@@ -21,8 +21,7 @@
|
||||
#include "render_backend.hpp"
|
||||
#include "tone_source.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
std::atomic<bool> g_running{true};
|
||||
|
||||
// Diagnostic: on an access violation, log the faulting address and the caller (return address on the
|
||||
@@ -30,17 +29,15 @@ std::atomic<bool> g_running{true};
|
||||
// crash so the test still detects it.
|
||||
LONG WINAPI crash_logger(EXCEPTION_POINTERS* ep)
|
||||
{
|
||||
if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
|
||||
{
|
||||
if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) {
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
auto mod = [](void* p, char* out, size_t n) -> unsigned long long {
|
||||
HMODULE m = nullptr;
|
||||
if (p != nullptr &&
|
||||
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
reinterpret_cast<LPCSTR>(p), &m) &&
|
||||
m != nullptr)
|
||||
{
|
||||
if (p != nullptr
|
||||
&& GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
reinterpret_cast<LPCSTR>(p), &m)
|
||||
&& m != nullptr) {
|
||||
char path[MAX_PATH] = {};
|
||||
GetModuleFileNameA(m, path, MAX_PATH);
|
||||
const char* base = std::strrchr(path, '\\');
|
||||
@@ -62,8 +59,7 @@ LONG WINAPI crash_logger(EXCEPTION_POINTERS* ep)
|
||||
|
||||
LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
if (msg == WM_DESTROY)
|
||||
{
|
||||
if (msg == WM_DESTROY) {
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
@@ -73,23 +69,18 @@ LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
// Spawns the audio render loop on its own thread (WASAPI wants its own COM apartment).
|
||||
void audio_thread(coop::tone::ToneFormat want)
|
||||
{
|
||||
if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)))
|
||||
{
|
||||
if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED))) {
|
||||
return;
|
||||
}
|
||||
coop::tone::ToneSource tone;
|
||||
if (tone.open(want, 440.0))
|
||||
{
|
||||
if (tone.open(want, 440.0)) {
|
||||
std::printf("MOCK_GAME audio: %u Hz %u ch %u-bit %s\n", tone.format().rate, tone.format().channels,
|
||||
tone.format().bits, tone.format().is_float ? "float" : "pcm");
|
||||
std::fflush(stdout);
|
||||
while (g_running.load(std::memory_order_relaxed))
|
||||
{
|
||||
while (g_running.load(std::memory_order_relaxed)) {
|
||||
tone.render_step(200);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
std::printf("MOCK_GAME audio: failed to open requested format\n");
|
||||
}
|
||||
tone.close();
|
||||
@@ -103,11 +94,11 @@ void audio_thread(coop::tone::ToneFormat want)
|
||||
void poll_input()
|
||||
{
|
||||
XINPUT_STATE xs{};
|
||||
(void)XInputGetState(0, &xs); // XInput hook (XInputGetState/Ex)
|
||||
(void)GetAsyncKeyState(VK_SPACE); // MKB hook (GetAsyncKeyState)
|
||||
(void)XInputGetState(0, &xs); // XInput hook (XInputGetState/Ex)
|
||||
(void)GetAsyncKeyState(VK_SPACE); // MKB hook (GetAsyncKeyState)
|
||||
BYTE kb[256] = {};
|
||||
(void)GetKeyboardState(kb); // MKB hook (GetKeyboardState)
|
||||
(void)GetForegroundWindow(); // focus hook (GetForegroundWindow)
|
||||
(void)GetKeyboardState(kb); // MKB hook (GetKeyboardState)
|
||||
(void)GetForegroundWindow(); // focus hook (GetForegroundWindow)
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -118,8 +109,7 @@ int main(int argc, char** argv)
|
||||
const double seconds = argc > 2 ? std::strtod(argv[2], nullptr) : 0.0;
|
||||
const bool want_audio = argc > 3;
|
||||
coop::tone::ToneFormat audio_fmt;
|
||||
if (want_audio)
|
||||
{
|
||||
if (want_audio) {
|
||||
audio_fmt.rate = static_cast<unsigned>(std::strtoul(argv[3], nullptr, 10));
|
||||
audio_fmt.channels = argc > 4 ? static_cast<unsigned>(std::strtoul(argv[4], nullptr, 10)) : 2;
|
||||
audio_fmt.bits = argc > 5 ? static_cast<unsigned>(std::strtoul(argv[5], nullptr, 10)) : 32;
|
||||
@@ -139,11 +129,9 @@ int main(int argc, char** argv)
|
||||
|
||||
RECT r = {0, 0, static_cast<LONG>(kW), static_cast<LONG>(kH)};
|
||||
AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, FALSE);
|
||||
HWND hwnd = CreateWindowExW(0, wc.lpszClassName, L"CoopMockGame", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, nullptr,
|
||||
nullptr, inst, nullptr);
|
||||
if (hwnd == nullptr)
|
||||
{
|
||||
HWND hwnd = CreateWindowExW(0, wc.lpszClassName, L"CoopMockGame", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, nullptr, nullptr, inst, nullptr);
|
||||
if (hwnd == nullptr) {
|
||||
std::printf("MOCK_GAME error: CreateWindow failed\n");
|
||||
return 1;
|
||||
}
|
||||
@@ -151,26 +139,23 @@ int main(int argc, char** argv)
|
||||
// Test hook (early-load): Vulkan caches its present pointer at init, so the capture hook must
|
||||
// be in place before vkCreateInstance. Under COOP_MOCK_VK_EARLY the mock loads vulkan-1.dll
|
||||
// now and waits, giving an already-injected hook time to hook vkGetInstanceProcAddr first.
|
||||
if (backend_name == "vk" && GetEnvironmentVariableW(L"COOP_MOCK_VK_EARLY", nullptr, 0) != 0)
|
||||
{
|
||||
if (backend_name == "vk" && GetEnvironmentVariableW(L"COOP_MOCK_VK_EARLY", nullptr, 0) != 0) {
|
||||
LoadLibraryW(L"vulkan-1.dll");
|
||||
Sleep(1500);
|
||||
}
|
||||
|
||||
auto backend = coop::mock::RenderBackend::create(backend_name);
|
||||
if (!backend || !backend->init(hwnd, kW, kH))
|
||||
{
|
||||
if (!backend || !backend->init(hwnd, kW, kH)) {
|
||||
std::printf("MOCK_GAME error: backend '%s' unavailable\n", backend_name.c_str());
|
||||
return 2;
|
||||
}
|
||||
|
||||
std::printf("MOCK_GAME pid=%lu backend=%s w=%u h=%u audio=%s\n", GetCurrentProcessId(), backend->name(),
|
||||
kW, kH, want_audio ? "yes" : "no");
|
||||
std::printf("MOCK_GAME pid=%lu backend=%s w=%u h=%u audio=%s\n", GetCurrentProcessId(), backend->name(), kW, kH,
|
||||
want_audio ? "yes" : "no");
|
||||
std::fflush(stdout);
|
||||
|
||||
std::thread audio;
|
||||
if (want_audio)
|
||||
{
|
||||
if (want_audio) {
|
||||
audio = std::thread(audio_thread, audio_fmt);
|
||||
}
|
||||
|
||||
@@ -178,20 +163,16 @@ int main(int argc, char** argv)
|
||||
std::uint32_t frame = 0;
|
||||
ULONGLONG fps_window_start = start; // window-title fps: frames in the last ~second
|
||||
std::uint32_t fps_window_frames = 0;
|
||||
for (;;)
|
||||
{
|
||||
for (;;) {
|
||||
MSG msg;
|
||||
while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
if (msg.message == WM_QUIT) {
|
||||
g_running.store(false, std::memory_order_relaxed);
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
if (!g_running.load(std::memory_order_relaxed))
|
||||
{
|
||||
if (!g_running.load(std::memory_order_relaxed)) {
|
||||
break;
|
||||
}
|
||||
poll_input(); // drive the input/focus/MKB detours each frame, like a real game
|
||||
@@ -200,8 +181,7 @@ int main(int argc, char** argv)
|
||||
// Show the backend + a once-per-second-smoothed fps in the title bar.
|
||||
++fps_window_frames;
|
||||
const ULONGLONG now = GetTickCount64();
|
||||
if (now - fps_window_start >= 1000)
|
||||
{
|
||||
if (now - fps_window_start >= 1000) {
|
||||
const double fps = fps_window_frames * 1000.0 / static_cast<double>(now - fps_window_start);
|
||||
wchar_t title[128];
|
||||
swprintf(title, 128, L"CoopMockGame [%hs] - %.0f fps", backend->name(), fps);
|
||||
@@ -209,15 +189,13 @@ int main(int argc, char** argv)
|
||||
fps_window_start = now;
|
||||
fps_window_frames = 0;
|
||||
}
|
||||
if (seconds > 0.0 && (GetTickCount64() - start) >= static_cast<ULONGLONG>(seconds * 1000.0))
|
||||
{
|
||||
if (seconds > 0.0 && (GetTickCount64() - start) >= static_cast<ULONGLONG>(seconds * 1000.0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_running.store(false, std::memory_order_relaxed);
|
||||
if (audio.joinable())
|
||||
{
|
||||
if (audio.joinable()) {
|
||||
audio.join();
|
||||
}
|
||||
std::printf("MOCK_GAME done: %u frames\n", frame);
|
||||
|
||||
@@ -1,36 +1,28 @@
|
||||
#include "render_backend.hpp"
|
||||
|
||||
namespace coop::mock
|
||||
{
|
||||
namespace coop::mock {
|
||||
|
||||
std::unique_ptr<RenderBackend> RenderBackend::create(const std::string& name)
|
||||
{
|
||||
if (name == "dx11")
|
||||
{
|
||||
if (name == "dx11") {
|
||||
return create_dx11_backend();
|
||||
}
|
||||
if (name == "dx12")
|
||||
{
|
||||
if (name == "dx12") {
|
||||
return create_dx12_backend();
|
||||
}
|
||||
if (name == "dx10")
|
||||
{
|
||||
if (name == "dx10") {
|
||||
return create_dx10_backend();
|
||||
}
|
||||
if (name == "dx9ex")
|
||||
{
|
||||
if (name == "dx9ex") {
|
||||
return create_dx9_backend(/*ex=*/true);
|
||||
}
|
||||
if (name == "dx9")
|
||||
{
|
||||
if (name == "dx9") {
|
||||
return create_dx9_backend(/*ex=*/false);
|
||||
}
|
||||
if (name == "gl" || name == "opengl")
|
||||
{
|
||||
if (name == "gl" || name == "opengl") {
|
||||
return create_gl_backend();
|
||||
}
|
||||
if (name == "vk" || name == "vulkan")
|
||||
{
|
||||
if (name == "vk" || name == "vulkan") {
|
||||
return create_vk_backend();
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace coop::mock
|
||||
{
|
||||
namespace coop::mock {
|
||||
|
||||
// Encode a frame counter into an RGB triple (and back). R/G/B are the low 24 bits, so it
|
||||
// is unambiguous for ~16M frames. The swap chain is UNORM (not sRGB), so the bytes survive
|
||||
@@ -30,8 +29,7 @@ inline void frame_to_rgb(std::uint32_t frame, std::uint8_t& r, std::uint8_t& g,
|
||||
|
||||
inline std::uint32_t rgb_to_frame(std::uint8_t r, std::uint8_t g, std::uint8_t b)
|
||||
{
|
||||
return static_cast<std::uint32_t>(r) | (static_cast<std::uint32_t>(g) << 8) |
|
||||
(static_cast<std::uint32_t>(b) << 16);
|
||||
return static_cast<std::uint32_t>(r) | (static_cast<std::uint32_t>(g) << 8) | (static_cast<std::uint32_t>(b) << 16);
|
||||
}
|
||||
|
||||
// Size (px) of the top-left frame-counter block the test samples.
|
||||
@@ -44,8 +42,7 @@ inline constexpr std::uint32_t kBarWidth = 24;
|
||||
// IDENTICAL image (the capture test compares backends). Each backend consumes these values with its
|
||||
// own API's clear/fill calls: an animated full-screen background, a kBarWidth-wide full-height white
|
||||
// bar at bar_x, and the top-left kFrameBlock-square frame-counter block whose colour encodes `frame`.
|
||||
struct FramePattern
|
||||
{
|
||||
struct FramePattern {
|
||||
std::uint8_t bg_r, bg_g, bg_b; // background; each channel sweeps at a different rate -> motion
|
||||
std::uint32_t bar_x; // left edge of the moving bar
|
||||
std::uint8_t code_r, code_g, code_b; // frame-counter block colour (frame_to_rgb)
|
||||
@@ -63,9 +60,8 @@ inline FramePattern frame_pattern(std::uint32_t frame, std::uint32_t width)
|
||||
return p;
|
||||
}
|
||||
|
||||
class RenderBackend
|
||||
{
|
||||
public:
|
||||
class RenderBackend {
|
||||
public:
|
||||
virtual ~RenderBackend() = default;
|
||||
|
||||
// Bring up the device + swap chain on `hwnd` at the given client size. False on failure.
|
||||
|
||||
@@ -10,21 +10,16 @@
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
namespace coop::mock
|
||||
{
|
||||
namespace
|
||||
{
|
||||
namespace coop::mock {
|
||||
namespace {
|
||||
D3DCOLOR opaque(std::uint8_t r, std::uint8_t g, std::uint8_t b)
|
||||
{
|
||||
return D3DCOLOR_ARGB(255, r, g, b);
|
||||
}
|
||||
|
||||
class Dx9Backend : public RenderBackend
|
||||
{
|
||||
public:
|
||||
explicit Dx9Backend(bool ex) : ex_(ex)
|
||||
{
|
||||
}
|
||||
class Dx9Backend : public RenderBackend {
|
||||
public:
|
||||
explicit Dx9Backend(bool ex) : ex_(ex) {}
|
||||
|
||||
bool init(HWND hwnd, std::uint32_t width, std::uint32_t height) override
|
||||
{
|
||||
@@ -41,32 +36,24 @@ public:
|
||||
pp.Windowed = TRUE;
|
||||
pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // uncapped: the mock must be fast
|
||||
|
||||
if (ex_)
|
||||
{
|
||||
if (ex_) {
|
||||
ComPtr<IDirect3D9Ex> d3d;
|
||||
if (FAILED(Direct3DCreate9Ex(D3D_SDK_VERSION, d3d.GetAddressOf())))
|
||||
{
|
||||
if (FAILED(Direct3DCreate9Ex(D3D_SDK_VERSION, d3d.GetAddressOf()))) {
|
||||
return false;
|
||||
}
|
||||
ComPtr<IDirect3DDevice9Ex> dev;
|
||||
if (FAILED(d3d->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
|
||||
D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, nullptr,
|
||||
dev.GetAddressOf())))
|
||||
{
|
||||
D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, nullptr, dev.GetAddressOf()))) {
|
||||
return false;
|
||||
}
|
||||
dev_ = dev; // IDirect3DDevice9Ex derives from IDirect3DDevice9
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
ComPtr<IDirect3D9> d3d(Direct3DCreate9(D3D_SDK_VERSION));
|
||||
if (!d3d)
|
||||
{
|
||||
if (!d3d) {
|
||||
return false;
|
||||
}
|
||||
if (FAILED(d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
|
||||
D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, dev_.GetAddressOf())))
|
||||
{
|
||||
if (FAILED(d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING,
|
||||
&pp, dev_.GetAddressOf()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -79,8 +66,7 @@ public:
|
||||
dev_->Clear(0, nullptr, D3DCLEAR_TARGET, opaque(p.bg_r, p.bg_g, p.bg_b), 1.0f, 0);
|
||||
|
||||
ComPtr<IDirect3DSurface9> back;
|
||||
if (SUCCEEDED(dev_->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, back.GetAddressOf())))
|
||||
{
|
||||
if (SUCCEEDED(dev_->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, back.GetAddressOf()))) {
|
||||
const LONG bx = static_cast<LONG>(p.bar_x);
|
||||
RECT bar = {bx, 0, bx + static_cast<LONG>(kBarWidth), static_cast<LONG>(height_)}; // moving vertical bar
|
||||
dev_->ColorFill(back.Get(), &bar, opaque(255, 255, 255));
|
||||
@@ -92,12 +78,9 @@ public:
|
||||
dev_->Present(nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
[[nodiscard]] const char* name() const override
|
||||
{
|
||||
return ex_ ? "dx9ex" : "dx9";
|
||||
}
|
||||
[[nodiscard]] const char* name() const override { return ex_ ? "dx9ex" : "dx9"; }
|
||||
|
||||
private:
|
||||
private:
|
||||
bool ex_;
|
||||
std::uint32_t width_ = 0;
|
||||
std::uint32_t height_ = 0;
|
||||
|
||||
@@ -13,20 +13,17 @@
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
namespace coop::mock
|
||||
{
|
||||
namespace
|
||||
{
|
||||
namespace coop::mock {
|
||||
namespace {
|
||||
std::uint32_t pack(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a = 255)
|
||||
{
|
||||
// R8G8B8A8_UNORM byte order: R in the low byte.
|
||||
return static_cast<std::uint32_t>(r) | (static_cast<std::uint32_t>(g) << 8) |
|
||||
(static_cast<std::uint32_t>(b) << 16) | (static_cast<std::uint32_t>(a) << 24);
|
||||
return static_cast<std::uint32_t>(r) | (static_cast<std::uint32_t>(g) << 8) | (static_cast<std::uint32_t>(b) << 16)
|
||||
| (static_cast<std::uint32_t>(a) << 24);
|
||||
}
|
||||
|
||||
class Dx10Backend : public RenderBackend
|
||||
{
|
||||
public:
|
||||
class Dx10Backend : public RenderBackend {
|
||||
public:
|
||||
bool init(HWND hwnd, std::uint32_t width, std::uint32_t height) override
|
||||
{
|
||||
width_ = width;
|
||||
@@ -46,10 +43,8 @@ public:
|
||||
desc.Windowed = TRUE;
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // blt model: GetBuffer(0) is the back buffer
|
||||
|
||||
if (FAILED(D3D10CreateDeviceAndSwapChain(nullptr, D3D10_DRIVER_TYPE_HARDWARE, nullptr, 0,
|
||||
D3D10_SDK_VERSION, &desc, swap_.GetAddressOf(),
|
||||
device_.GetAddressOf())))
|
||||
{
|
||||
if (FAILED(D3D10CreateDeviceAndSwapChain(nullptr, D3D10_DRIVER_TYPE_HARDWARE, nullptr, 0, D3D10_SDK_VERSION,
|
||||
&desc, swap_.GetAddressOf(), device_.GetAddressOf()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -75,18 +70,14 @@ public:
|
||||
const std::uint32_t code = pack(p.code_r, p.code_g, p.code_b);
|
||||
|
||||
const std::uint32_t bx = p.bar_x; // moving vertical bar
|
||||
for (std::uint32_t y = 0; y < height_; ++y)
|
||||
{
|
||||
for (std::uint32_t y = 0; y < height_; ++y) {
|
||||
std::uint32_t* row = px_.data() + static_cast<std::size_t>(y) * width_;
|
||||
for (std::uint32_t x = 0; x < width_; ++x)
|
||||
{
|
||||
for (std::uint32_t x = 0; x < width_; ++x) {
|
||||
std::uint32_t c = bg;
|
||||
if (x >= bx && x < bx + kBarWidth)
|
||||
{
|
||||
if (x >= bx && x < bx + kBarWidth) {
|
||||
c = whitepx;
|
||||
}
|
||||
if (x < kFrameBlock && y < kFrameBlock)
|
||||
{
|
||||
if (x < kFrameBlock && y < kFrameBlock) {
|
||||
c = code; // top-left frame-counter block
|
||||
}
|
||||
row[x] = c;
|
||||
@@ -95,19 +86,15 @@ public:
|
||||
|
||||
device_->UpdateSubresource(scratch_.Get(), 0, nullptr, px_.data(), static_cast<UINT>(width_ * 4), 0);
|
||||
ComPtr<ID3D10Texture2D> back;
|
||||
if (SUCCEEDED(swap_->GetBuffer(0, IID_PPV_ARGS(back.GetAddressOf()))))
|
||||
{
|
||||
if (SUCCEEDED(swap_->GetBuffer(0, IID_PPV_ARGS(back.GetAddressOf())))) {
|
||||
device_->CopyResource(back.Get(), scratch_.Get());
|
||||
}
|
||||
swap_->Present(0, 0); // uncapped (BLT model): the mock does nothing -> it must be fast
|
||||
}
|
||||
|
||||
[[nodiscard]] const char* name() const override
|
||||
{
|
||||
return "dx10";
|
||||
}
|
||||
[[nodiscard]] const char* name() const override { return "dx10"; }
|
||||
|
||||
private:
|
||||
private:
|
||||
std::uint32_t width_ = 0;
|
||||
std::uint32_t height_ = 0;
|
||||
std::vector<std::uint32_t> px_;
|
||||
|
||||
@@ -9,13 +9,10 @@
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
namespace coop::mock
|
||||
{
|
||||
namespace
|
||||
{
|
||||
class Dx11Backend : public RenderBackend
|
||||
{
|
||||
public:
|
||||
namespace coop::mock {
|
||||
namespace {
|
||||
class Dx11Backend : public RenderBackend {
|
||||
public:
|
||||
bool init(HWND hwnd, std::uint32_t width, std::uint32_t height) override
|
||||
{
|
||||
width_ = width;
|
||||
@@ -24,9 +21,8 @@ public:
|
||||
const D3D_FEATURE_LEVEL levels[] = {D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0};
|
||||
ComPtr<ID3D11DeviceContext> ctx0;
|
||||
if (FAILED(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, levels,
|
||||
static_cast<UINT>(std::size(levels)), D3D11_SDK_VERSION,
|
||||
device_.GetAddressOf(), nullptr, ctx0.GetAddressOf())))
|
||||
{
|
||||
static_cast<UINT>(std::size(levels)), D3D11_SDK_VERSION, device_.GetAddressOf(),
|
||||
nullptr, ctx0.GetAddressOf()))) {
|
||||
return false;
|
||||
}
|
||||
if (FAILED(ctx0.As(&ctx_))) // ClearView needs ID3D11DeviceContext1
|
||||
@@ -37,9 +33,8 @@ public:
|
||||
ComPtr<IDXGIDevice> dxgi_device;
|
||||
ComPtr<IDXGIAdapter> adapter;
|
||||
ComPtr<IDXGIFactory2> factory;
|
||||
if (FAILED(device_.As(&dxgi_device)) || FAILED(dxgi_device->GetAdapter(adapter.GetAddressOf())) ||
|
||||
FAILED(adapter->GetParent(IID_PPV_ARGS(factory.GetAddressOf()))))
|
||||
{
|
||||
if (FAILED(device_.As(&dxgi_device)) || FAILED(dxgi_device->GetAdapter(adapter.GetAddressOf()))
|
||||
|| FAILED(adapter->GetParent(IID_PPV_ARGS(factory.GetAddressOf())))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -47,8 +42,7 @@ public:
|
||||
// game) -- a flip-model swapchain only tears free of vsync with ALLOW_TEARING, so require it.
|
||||
ComPtr<IDXGIFactory5> factory5;
|
||||
BOOL tearing = FALSE;
|
||||
if (SUCCEEDED(factory.As(&factory5)))
|
||||
{
|
||||
if (SUCCEEDED(factory.As(&factory5))) {
|
||||
factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &tearing, sizeof(tearing));
|
||||
}
|
||||
tearing_ = tearing != 0;
|
||||
@@ -62,18 +56,16 @@ public:
|
||||
desc.BufferCount = 2;
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
desc.Flags = tearing_ ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0u;
|
||||
if (FAILED(factory->CreateSwapChainForHwnd(device_.Get(), hwnd, &desc, nullptr, nullptr,
|
||||
swap_.GetAddressOf())))
|
||||
{
|
||||
if (FAILED(
|
||||
factory->CreateSwapChainForHwnd(device_.Get(), hwnd, &desc, nullptr, nullptr, swap_.GetAddressOf()))) {
|
||||
return false;
|
||||
}
|
||||
factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
|
||||
|
||||
// D3D11 flip-model: GetBuffer(0) stays the live back buffer, so one RTV is reused.
|
||||
ComPtr<ID3D11Texture2D> back;
|
||||
if (FAILED(swap_->GetBuffer(0, IID_PPV_ARGS(back.GetAddressOf()))) ||
|
||||
FAILED(device_->CreateRenderTargetView(back.Get(), nullptr, rtv_.GetAddressOf())))
|
||||
{
|
||||
if (FAILED(swap_->GetBuffer(0, IID_PPV_ARGS(back.GetAddressOf())))
|
||||
|| FAILED(device_->CreateRenderTargetView(back.Get(), nullptr, rtv_.GetAddressOf()))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -98,12 +90,9 @@ public:
|
||||
swap_->Present(0, tearing_ ? DXGI_PRESENT_ALLOW_TEARING : 0u); // uncapped: the mock must be fast
|
||||
}
|
||||
|
||||
[[nodiscard]] const char* name() const override
|
||||
{
|
||||
return "dx11";
|
||||
}
|
||||
[[nodiscard]] const char* name() const override { return "dx11"; }
|
||||
|
||||
private:
|
||||
private:
|
||||
std::uint32_t width_ = 0;
|
||||
std::uint32_t height_ = 0;
|
||||
bool tearing_ = false;
|
||||
|
||||
@@ -9,43 +9,36 @@
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
namespace coop::mock
|
||||
{
|
||||
namespace
|
||||
{
|
||||
namespace coop::mock {
|
||||
namespace {
|
||||
constexpr UINT kBackBuffers = 3; // DX12 rotates these explicitly -- the case the capture must get right
|
||||
|
||||
class Dx12Backend : public RenderBackend
|
||||
{
|
||||
public:
|
||||
class Dx12Backend : public RenderBackend {
|
||||
public:
|
||||
bool init(HWND hwnd, std::uint32_t width, std::uint32_t height) override
|
||||
{
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
|
||||
if (FAILED(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(device_.GetAddressOf()))))
|
||||
{
|
||||
if (FAILED(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(device_.GetAddressOf())))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC qd = {};
|
||||
qd.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
if (FAILED(device_->CreateCommandQueue(&qd, IID_PPV_ARGS(queue_.GetAddressOf()))))
|
||||
{
|
||||
if (FAILED(device_->CreateCommandQueue(&qd, IID_PPV_ARGS(queue_.GetAddressOf())))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ComPtr<IDXGIFactory4> factory;
|
||||
if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(factory.GetAddressOf()))))
|
||||
{
|
||||
if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(factory.GetAddressOf())))) {
|
||||
return false;
|
||||
}
|
||||
// Uncapped (the mock is a perf fixture): a flip-model swapchain needs ALLOW_TEARING to run
|
||||
// free of vsync.
|
||||
ComPtr<IDXGIFactory5> factory5;
|
||||
BOOL tearing = FALSE;
|
||||
if (SUCCEEDED(factory.As(&factory5)))
|
||||
{
|
||||
if (SUCCEEDED(factory.As(&factory5))) {
|
||||
factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &tearing, sizeof(tearing));
|
||||
}
|
||||
tearing_ = tearing != 0;
|
||||
@@ -60,10 +53,8 @@ public:
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
desc.Flags = tearing_ ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0u;
|
||||
ComPtr<IDXGISwapChain1> sc1;
|
||||
if (FAILED(factory->CreateSwapChainForHwnd(queue_.Get(), hwnd, &desc, nullptr, nullptr,
|
||||
sc1.GetAddressOf())) ||
|
||||
FAILED(sc1.As(&swap_)))
|
||||
{
|
||||
if (FAILED(factory->CreateSwapChainForHwnd(queue_.Get(), hwnd, &desc, nullptr, nullptr, sc1.GetAddressOf()))
|
||||
|| FAILED(sc1.As(&swap_))) {
|
||||
return false;
|
||||
}
|
||||
factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
|
||||
@@ -71,36 +62,30 @@ public:
|
||||
D3D12_DESCRIPTOR_HEAP_DESC hd = {};
|
||||
hd.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
hd.NumDescriptors = kBackBuffers;
|
||||
if (FAILED(device_->CreateDescriptorHeap(&hd, IID_PPV_ARGS(rtv_heap_.GetAddressOf()))))
|
||||
{
|
||||
if (FAILED(device_->CreateDescriptorHeap(&hd, IID_PPV_ARGS(rtv_heap_.GetAddressOf())))) {
|
||||
return false;
|
||||
}
|
||||
rtv_stride_ = device_->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE h = rtv_heap_->GetCPUDescriptorHandleForHeapStart();
|
||||
for (UINT i = 0; i < kBackBuffers; ++i)
|
||||
{
|
||||
if (FAILED(swap_->GetBuffer(i, IID_PPV_ARGS(targets_[i].GetAddressOf()))))
|
||||
{
|
||||
for (UINT i = 0; i < kBackBuffers; ++i) {
|
||||
if (FAILED(swap_->GetBuffer(i, IID_PPV_ARGS(targets_[i].GetAddressOf())))) {
|
||||
return false;
|
||||
}
|
||||
device_->CreateRenderTargetView(targets_[i].Get(), nullptr, h);
|
||||
rtv_handles_[i] = h;
|
||||
h.ptr += rtv_stride_;
|
||||
if (FAILED(device_->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
IID_PPV_ARGS(allocs_[i].GetAddressOf()))))
|
||||
{
|
||||
IID_PPV_ARGS(allocs_[i].GetAddressOf())))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (FAILED(device_->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, allocs_[0].Get(), nullptr,
|
||||
IID_PPV_ARGS(list_.GetAddressOf()))))
|
||||
{
|
||||
IID_PPV_ARGS(list_.GetAddressOf())))) {
|
||||
return false;
|
||||
}
|
||||
list_->Close();
|
||||
|
||||
if (FAILED(device_->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(fence_.GetAddressOf()))))
|
||||
{
|
||||
if (FAILED(device_->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(fence_.GetAddressOf())))) {
|
||||
return false;
|
||||
}
|
||||
fence_event_ = CreateEventW(nullptr, FALSE, FALSE, nullptr);
|
||||
@@ -138,24 +123,19 @@ public:
|
||||
wait_for_gpu(); // simple per-frame sync (mock game: correctness over throughput)
|
||||
}
|
||||
|
||||
[[nodiscard]] const char* name() const override
|
||||
{
|
||||
return "dx12";
|
||||
}
|
||||
[[nodiscard]] const char* name() const override { return "dx12"; }
|
||||
|
||||
~Dx12Backend() override
|
||||
{
|
||||
if (fence_ != nullptr)
|
||||
{
|
||||
if (fence_ != nullptr) {
|
||||
wait_for_gpu();
|
||||
}
|
||||
if (fence_event_ != nullptr)
|
||||
{
|
||||
if (fence_event_ != nullptr) {
|
||||
CloseHandle(fence_event_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
void transition(ID3D12Resource* res, D3D12_RESOURCE_STATES from, D3D12_RESOURCE_STATES to)
|
||||
{
|
||||
D3D12_RESOURCE_BARRIER b = {};
|
||||
@@ -171,8 +151,7 @@ private:
|
||||
{
|
||||
const UINT64 v = ++fence_value_;
|
||||
queue_->Signal(fence_.Get(), v);
|
||||
if (fence_->GetCompletedValue() < v)
|
||||
{
|
||||
if (fence_->GetCompletedValue() < v) {
|
||||
fence_->SetEventOnCompletion(v, fence_event_);
|
||||
WaitForSingleObject(fence_event_, INFINITE);
|
||||
}
|
||||
|
||||
@@ -12,21 +12,17 @@
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
namespace coop::mock
|
||||
{
|
||||
namespace
|
||||
{
|
||||
class GlBackend : public RenderBackend
|
||||
{
|
||||
public:
|
||||
namespace coop::mock {
|
||||
namespace {
|
||||
class GlBackend : public RenderBackend {
|
||||
public:
|
||||
bool init(HWND hwnd, std::uint32_t width, std::uint32_t height) override
|
||||
{
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
hwnd_ = hwnd;
|
||||
hdc_ = GetDC(hwnd);
|
||||
if (hdc_ == nullptr)
|
||||
{
|
||||
if (hdc_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
PIXELFORMATDESCRIPTOR pfd = {};
|
||||
@@ -38,20 +34,17 @@ public:
|
||||
pfd.cAlphaBits = 8;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
const int pf = ChoosePixelFormat(hdc_, &pfd);
|
||||
if (pf == 0 || !SetPixelFormat(hdc_, pf, &pfd))
|
||||
{
|
||||
if (pf == 0 || !SetPixelFormat(hdc_, pf, &pfd)) {
|
||||
return false;
|
||||
}
|
||||
hglrc_ = wglCreateContext(hdc_); // legacy context is enough for GL 1.1 clears
|
||||
if (hglrc_ == nullptr || !wglMakeCurrent(hdc_, hglrc_))
|
||||
{
|
||||
if (hglrc_ == nullptr || !wglMakeCurrent(hdc_, hglrc_)) {
|
||||
return false;
|
||||
}
|
||||
// Uncapped: the mock is a perf fixture and must run as fast as it can (disable vsync), so a
|
||||
// capture-induced slowdown is visible. Runtime extension lookup -- no loader/submodule needed.
|
||||
using PFN_wglSwapIntervalEXT = BOOL(WINAPI*)(int);
|
||||
if (auto swap_interval = reinterpret_cast<PFN_wglSwapIntervalEXT>(wglGetProcAddress("wglSwapIntervalEXT")))
|
||||
{
|
||||
if (auto swap_interval = reinterpret_cast<PFN_wglSwapIntervalEXT>(wglGetProcAddress("wglSwapIntervalEXT"))) {
|
||||
swap_interval(0);
|
||||
}
|
||||
return true;
|
||||
@@ -87,25 +80,20 @@ public:
|
||||
SwapBuffers(hdc_); // the capture hook intercepts this
|
||||
}
|
||||
|
||||
[[nodiscard]] const char* name() const override
|
||||
{
|
||||
return "gl";
|
||||
}
|
||||
[[nodiscard]] const char* name() const override { return "gl"; }
|
||||
|
||||
~GlBackend() override
|
||||
{
|
||||
wglMakeCurrent(nullptr, nullptr);
|
||||
if (hglrc_ != nullptr)
|
||||
{
|
||||
if (hglrc_ != nullptr) {
|
||||
wglDeleteContext(hglrc_);
|
||||
}
|
||||
if (hdc_ != nullptr && hwnd_ != nullptr)
|
||||
{
|
||||
if (hdc_ != nullptr && hwnd_ != nullptr) {
|
||||
ReleaseDC(hwnd_, hdc_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
std::uint32_t width_ = 0;
|
||||
std::uint32_t height_ = 0;
|
||||
HWND hwnd_ = nullptr;
|
||||
|
||||
@@ -10,19 +10,15 @@
|
||||
|
||||
#include <volk.h>
|
||||
|
||||
namespace coop::mock
|
||||
{
|
||||
namespace
|
||||
{
|
||||
class VkBackend : public RenderBackend
|
||||
{
|
||||
public:
|
||||
namespace coop::mock {
|
||||
namespace {
|
||||
class VkBackend : public RenderBackend {
|
||||
public:
|
||||
bool init(HWND hwnd, std::uint32_t width, std::uint32_t height) override
|
||||
{
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
if (volkInitialize() != VK_SUCCESS)
|
||||
{
|
||||
if (volkInitialize() != VK_SUCCESS) {
|
||||
return false; // no Vulkan loader on this machine
|
||||
}
|
||||
|
||||
@@ -34,8 +30,7 @@ public:
|
||||
ici.pApplicationInfo = &app;
|
||||
ici.enabledExtensionCount = 2;
|
||||
ici.ppEnabledExtensionNames = inst_ext;
|
||||
if (vkCreateInstance(&ici, nullptr, &instance_) != VK_SUCCESS)
|
||||
{
|
||||
if (vkCreateInstance(&ici, nullptr, &instance_) != VK_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
volkLoadInstance(instance_);
|
||||
@@ -43,13 +38,11 @@ public:
|
||||
VkWin32SurfaceCreateInfoKHR sci{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR};
|
||||
sci.hinstance = GetModuleHandleW(nullptr);
|
||||
sci.hwnd = hwnd;
|
||||
if (vkCreateWin32SurfaceKHR(instance_, &sci, nullptr, &surface_) != VK_SUCCESS)
|
||||
{
|
||||
if (vkCreateWin32SurfaceKHR(instance_, &sci, nullptr, &surface_) != VK_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pick_device() || !create_device() || !create_swapchain() || !create_commands())
|
||||
{
|
||||
if (!pick_device() || !create_device() || !create_swapchain() || !create_commands()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -57,20 +50,17 @@ public:
|
||||
|
||||
void render_and_present(std::uint32_t frame) override
|
||||
{
|
||||
if (device_ == VK_NULL_HANDLE || swapchain_ == VK_NULL_HANDLE)
|
||||
{
|
||||
if (device_ == VK_NULL_HANDLE || swapchain_ == VK_NULL_HANDLE) {
|
||||
return;
|
||||
}
|
||||
vkWaitForFences(device_, 1, &in_flight_, VK_TRUE, UINT64_MAX);
|
||||
|
||||
std::uint32_t idx = 0;
|
||||
VkResult acq = vkAcquireNextImageKHR(device_, swapchain_, UINT64_MAX, acquire_sem_, VK_NULL_HANDLE, &idx);
|
||||
if (acq == VK_ERROR_OUT_OF_DATE_KHR || acq == VK_SUBOPTIMAL_KHR)
|
||||
{
|
||||
if (acq == VK_ERROR_OUT_OF_DATE_KHR || acq == VK_SUBOPTIMAL_KHR) {
|
||||
return; // skip this frame (the mock window isn't resized in practice)
|
||||
}
|
||||
if (acq != VK_SUCCESS)
|
||||
{
|
||||
if (acq != VK_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
vkResetFences(device_, 1, &in_flight_);
|
||||
@@ -118,15 +108,11 @@ public:
|
||||
vkQueuePresentKHR(queue_, &pi);
|
||||
}
|
||||
|
||||
[[nodiscard]] const char* name() const override
|
||||
{
|
||||
return "vk";
|
||||
}
|
||||
[[nodiscard]] const char* name() const override { return "vk"; }
|
||||
|
||||
~VkBackend() override
|
||||
{
|
||||
if (device_ != VK_NULL_HANDLE)
|
||||
{
|
||||
if (device_ != VK_NULL_HANDLE) {
|
||||
vkDeviceWaitIdle(device_);
|
||||
if (in_flight_ != VK_NULL_HANDLE)
|
||||
vkDestroyFence(device_, in_flight_, nullptr);
|
||||
@@ -146,25 +132,22 @@ public:
|
||||
vkDestroyInstance(instance_, nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
bool pick_device()
|
||||
{
|
||||
std::uint32_t n = 0;
|
||||
vkEnumeratePhysicalDevices(instance_, &n, nullptr);
|
||||
std::vector<VkPhysicalDevice> devs(n);
|
||||
vkEnumeratePhysicalDevices(instance_, &n, devs.data());
|
||||
for (VkPhysicalDevice pd : devs)
|
||||
{
|
||||
for (VkPhysicalDevice pd : devs) {
|
||||
std::uint32_t qn = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(pd, &qn, nullptr);
|
||||
std::vector<VkQueueFamilyProperties> qf(qn);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(pd, &qn, qf.data());
|
||||
for (std::uint32_t i = 0; i < qn; ++i)
|
||||
{
|
||||
for (std::uint32_t i = 0; i < qn; ++i) {
|
||||
VkBool32 present = VK_FALSE;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(pd, i, surface_, &present);
|
||||
if ((qf[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && present)
|
||||
{
|
||||
if ((qf[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && present) {
|
||||
phys_ = pd;
|
||||
qfam_ = i;
|
||||
return true;
|
||||
@@ -187,8 +170,7 @@ private:
|
||||
dci.pQueueCreateInfos = &qci;
|
||||
dci.enabledExtensionCount = 1;
|
||||
dci.ppEnabledExtensionNames = dev_ext;
|
||||
if (vkCreateDevice(phys_, &dci, nullptr, &device_) != VK_SUCCESS)
|
||||
{
|
||||
if (vkCreateDevice(phys_, &dci, nullptr, &device_) != VK_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
volkLoadDevice(device_);
|
||||
@@ -205,13 +187,11 @@ private:
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(phys_, surface_, &fn, nullptr);
|
||||
std::vector<VkSurfaceFormatKHR> formats(fn);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(phys_, surface_, &fn, formats.data());
|
||||
VkSurfaceFormatKHR chosen = formats.empty() ? VkSurfaceFormatKHR{VK_FORMAT_B8G8R8A8_UNORM,
|
||||
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}
|
||||
: formats[0];
|
||||
for (const VkSurfaceFormatKHR& f : formats)
|
||||
{
|
||||
if (f.format == VK_FORMAT_B8G8R8A8_UNORM || f.format == VK_FORMAT_R8G8B8A8_UNORM)
|
||||
{
|
||||
VkSurfaceFormatKHR chosen =
|
||||
formats.empty() ? VkSurfaceFormatKHR{VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}
|
||||
: formats[0];
|
||||
for (const VkSurfaceFormatKHR& f : formats) {
|
||||
if (f.format == VK_FORMAT_B8G8R8A8_UNORM || f.format == VK_FORMAT_R8G8B8A8_UNORM) {
|
||||
chosen = f;
|
||||
break;
|
||||
}
|
||||
@@ -219,8 +199,7 @@ private:
|
||||
format_ = chosen.format;
|
||||
|
||||
std::uint32_t want = caps.minImageCount + 1;
|
||||
if (caps.maxImageCount > 0 && want > caps.maxImageCount)
|
||||
{
|
||||
if (caps.maxImageCount > 0 && want > caps.maxImageCount) {
|
||||
want = caps.maxImageCount;
|
||||
}
|
||||
VkSwapchainCreateInfoKHR sc{VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR};
|
||||
@@ -228,9 +207,7 @@ private:
|
||||
sc.minImageCount = want;
|
||||
sc.imageFormat = chosen.format;
|
||||
sc.imageColorSpace = chosen.colorSpace;
|
||||
sc.imageExtent = caps.currentExtent.width != 0xFFFFFFFFu
|
||||
? caps.currentExtent
|
||||
: VkExtent2D{width_, height_};
|
||||
sc.imageExtent = caps.currentExtent.width != 0xFFFFFFFFu ? caps.currentExtent : VkExtent2D{width_, height_};
|
||||
sc.imageArrayLayers = 1;
|
||||
// TRANSFER_DST so we can clear it; TRANSFER_SRC so the capture hook can copy it out.
|
||||
sc.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
@@ -249,12 +226,11 @@ private:
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
sc.presentMode = has_mode(VK_PRESENT_MODE_IMMEDIATE_KHR) ? VK_PRESENT_MODE_IMMEDIATE_KHR
|
||||
sc.presentMode = has_mode(VK_PRESENT_MODE_IMMEDIATE_KHR) ? VK_PRESENT_MODE_IMMEDIATE_KHR
|
||||
: has_mode(VK_PRESENT_MODE_MAILBOX_KHR) ? VK_PRESENT_MODE_MAILBOX_KHR
|
||||
: VK_PRESENT_MODE_FIFO_KHR;
|
||||
: VK_PRESENT_MODE_FIFO_KHR;
|
||||
sc.clipped = VK_TRUE;
|
||||
if (vkCreateSwapchainKHR(device_, &sc, nullptr, &swapchain_) != VK_SUCCESS)
|
||||
{
|
||||
if (vkCreateSwapchainKHR(device_, &sc, nullptr, &swapchain_) != VK_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
std::uint32_t in = 0;
|
||||
@@ -269,29 +245,26 @@ private:
|
||||
VkCommandPoolCreateInfo pci{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
|
||||
pci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
pci.queueFamilyIndex = qfam_;
|
||||
if (vkCreateCommandPool(device_, &pci, nullptr, &pool_) != VK_SUCCESS)
|
||||
{
|
||||
if (vkCreateCommandPool(device_, &pci, nullptr, &pool_) != VK_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
VkCommandBufferAllocateInfo ai{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};
|
||||
ai.commandPool = pool_;
|
||||
ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
ai.commandBufferCount = 1;
|
||||
if (vkAllocateCommandBuffers(device_, &ai, &cmd_) != VK_SUCCESS)
|
||||
{
|
||||
if (vkAllocateCommandBuffers(device_, &ai, &cmd_) != VK_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
VkSemaphoreCreateInfo si{VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
|
||||
VkFenceCreateInfo fi{VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
|
||||
fi.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||
return vkCreateSemaphore(device_, &si, nullptr, &acquire_sem_) == VK_SUCCESS &&
|
||||
vkCreateSemaphore(device_, &si, nullptr, &submit_sem_) == VK_SUCCESS &&
|
||||
vkCreateFence(device_, &fi, nullptr, &in_flight_) == VK_SUCCESS;
|
||||
return vkCreateSemaphore(device_, &si, nullptr, &acquire_sem_) == VK_SUCCESS
|
||||
&& vkCreateSemaphore(device_, &si, nullptr, &submit_sem_) == VK_SUCCESS
|
||||
&& vkCreateFence(device_, &fi, nullptr, &in_flight_) == VK_SUCCESS;
|
||||
}
|
||||
|
||||
static void barrier(VkCommandBuffer cb, VkImage img, VkImageLayout from, VkImageLayout to,
|
||||
VkAccessFlags src_access, VkAccessFlags dst_access, VkPipelineStageFlags src_stage,
|
||||
VkPipelineStageFlags dst_stage)
|
||||
static void barrier(VkCommandBuffer cb, VkImage img, VkImageLayout from, VkImageLayout to, VkAccessFlags src_access,
|
||||
VkAccessFlags dst_access, VkPipelineStageFlags src_stage, VkPipelineStageFlags dst_stage)
|
||||
{
|
||||
VkImageMemoryBarrier b{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
|
||||
b.srcAccessMask = src_access;
|
||||
|
||||
Reference in New Issue
Block a user