From da40192913e6476bb079b315469360737764d37e Mon Sep 17 00:00:00 2001 From: kit rae Date: Fri, 6 Mar 2026 02:15:13 +0000 Subject: [PATCH] Revert "vulkan: add initial Windows64 renderer backend and chunk texturing fixes" This reverts commit 495f88bf7a254a5ee3054c8bdfc4ccaa2748e7e2 --- Minecraft.Client/Chunk.cpp | 8 - Minecraft.Client/Tesselator.cpp | 7 +- .../Windows64/C4JRender_Vulkan.cpp | 4608 ----------------- .../Windows64/VulkanTriangleShaders.inl | 145 - Minecraft.Client/Windows64/VulkanUIBridge.h | 6 - .../Windows64/VulkanUIShaders.inl | 87 - 6 files changed, 1 insertion(+), 4860 deletions(-) delete mode 100644 Minecraft.Client/Windows64/C4JRender_Vulkan.cpp delete mode 100644 Minecraft.Client/Windows64/VulkanTriangleShaders.inl delete mode 100644 Minecraft.Client/Windows64/VulkanUIBridge.h delete mode 100644 Minecraft.Client/Windows64/VulkanUIShaders.inl diff --git a/Minecraft.Client/Chunk.cpp b/Minecraft.Client/Chunk.cpp index bca0c93e..99933db3 100644 --- a/Minecraft.Client/Chunk.cpp +++ b/Minecraft.Client/Chunk.cpp @@ -385,11 +385,7 @@ void Chunk::rebuild() MemSect(0); glPushMatrix(); glDepthMask(true); // 4J added - #if defined(_XBOX) || defined(_XBOX_ONE) || defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) t->useCompactVertices(true); // 4J added - #else - t->useCompactVertices(false); // compact path on w vulkan caused uv decode issues, keep this false - #endif translateToPos(); float ss = 1.000001f; // 4J - have removed this scale as I don't think we should need it, and have now optimised the vertex @@ -708,11 +704,7 @@ void Chunk::rebuild_SPU() MemSect(0); glPushMatrix(); glDepthMask(true); // 4J added - #if defined(_XBOX) || defined(_XBOX_ONE) || defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) t->useCompactVertices(true); // 4J added - #else - t->useCompactVertices(false); // compact path on w vulkan caused uv decode issues, keep this false - #endif translateToPos(); float ss = 1.000001f; // 4J - have removed this scale as I don't think we should need it, and have now optimised the vertex diff --git a/Minecraft.Client/Tesselator.cpp b/Minecraft.Client/Tesselator.cpp index d424950e..366b09e3 100644 --- a/Minecraft.Client/Tesselator.cpp +++ b/Minecraft.Client/Tesselator.cpp @@ -231,12 +231,7 @@ void Tesselator::useProjectedTexture(bool enable) void Tesselator::useCompactVertices(bool enable) { -#if defined(_WIN32) && !defined(_XBOX) && !defined(_XBOX_ONE) - // windows vulkan: keep compact off for now, decoder not finished. - useCompactFormat360 = false; -#else useCompactFormat360 = enable; -#endif } bool Tesselator::getCompactVertices() @@ -1082,4 +1077,4 @@ bool Tesselator::hasMaxVertices() #else return false; #endif -} +} \ No newline at end of file diff --git a/Minecraft.Client/Windows64/C4JRender_Vulkan.cpp b/Minecraft.Client/Windows64/C4JRender_Vulkan.cpp deleted file mode 100644 index 322f564f..00000000 --- a/Minecraft.Client/Windows64/C4JRender_Vulkan.cpp +++ /dev/null @@ -1,4608 +0,0 @@ -// ============================================================================ -// C4JRender_Vulkan.cpp - Windows Vulkan backend for C4JRender. -// ============================================================================ -#include "stdafx.h" - -#define VK_USE_PLATFORM_WIN32_KHR -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "VulkanTriangleShaders.inl" -#include "VulkanUIShaders.inl" -#include "VulkanUIBridge.h" - -// ---- Global singleton ---- -C4JRender RenderManager; - -// ============================================================================ -// Internal state -// ============================================================================ - -static const int MATRIX_STACK_DEPTH = 32; -static const int NUM_MATRIX_MODES = 3; // modelview, projection, texture - -struct MatrixStack { - float stack[MATRIX_STACK_DEPTH][16]; - int top; -}; - -static thread_local MatrixStack g_matStacks[NUM_MATRIX_MODES]; -static thread_local int g_curMatrixMode = 0; // GL_MODELVIEW -static thread_local bool g_matrixDirty = true; -static thread_local bool g_matrixStacksInitialised = false; - -static void ensureThreadLocalMatrixStacksInitialised() { - if (g_matrixStacksInitialised) - return; - for (int i = 0; i < NUM_MATRIX_MODES; ++i) { - std::memset(g_matStacks[i].stack[0], 0, 16 * sizeof(float)); - g_matStacks[i].stack[0][0] = 1.0f; - g_matStacks[i].stack[0][5] = 1.0f; - g_matStacks[i].stack[0][10] = 1.0f; - g_matStacks[i].stack[0][15] = 1.0f; - g_matStacks[i].top = 0; - } - g_curMatrixMode = 0; - g_matrixDirty = true; - g_matrixStacksInitialised = true; -} - -// Vulkan objects -static VkInstance g_vkInstance = VK_NULL_HANDLE; -static VkPhysicalDevice g_vkPhysicalDevice = VK_NULL_HANDLE; -static VkDevice g_vkDevice = VK_NULL_HANDLE; -static VkQueue g_vkGraphicsQueue = VK_NULL_HANDLE; -static VkSurfaceKHR g_vkSurface = VK_NULL_HANDLE; -static HWND g_vkWindow = NULL; -static VkSwapchainKHR g_vkSwapchain = VK_NULL_HANDLE; -static VkRenderPass g_vkRenderPass = VK_NULL_HANDLE; -static VkPipelineLayout g_vkPipelineLayout = VK_NULL_HANDLE; -static VkPipeline g_vkTrianglePipeline = VK_NULL_HANDLE; -static std::unordered_map g_vkTrianglePipelines; -static VkDescriptorSetLayout g_vkTriangleDescriptorSetLayout = VK_NULL_HANDLE; -static VkDescriptorPool g_vkTriangleDescriptorPool = VK_NULL_HANDLE; -static VkDescriptorSetLayout g_vkUiDescriptorSetLayout = VK_NULL_HANDLE; -static VkDescriptorPool g_vkUiDescriptorPool = VK_NULL_HANDLE; -static VkDescriptorSet g_vkUiDescriptorSet = VK_NULL_HANDLE; -static VkPipelineLayout g_vkUiPipelineLayout = VK_NULL_HANDLE; -static VkPipeline g_vkUiPipeline = VK_NULL_HANDLE; -static VkCommandPool g_vkCommandPool = VK_NULL_HANDLE; -static VkCommandBuffer g_vkCommandBuffer = VK_NULL_HANDLE; -static VkFence g_vkFence = VK_NULL_HANDLE; -static VkSemaphore g_vkImageAvailable = VK_NULL_HANDLE; -static VkSemaphore g_vkRenderFinished = VK_NULL_HANDLE; -static uint32_t g_vkGraphicsFamily = 0; -static std::vector g_vkSwapImages; -static std::vector g_vkSwapImageViews; -static std::vector g_vkFramebuffers; -static std::vector g_vkSwapImageLayouts; -static VkFormat g_vkSwapFormat = VK_FORMAT_B8G8R8A8_UNORM; -static VkExtent2D g_vkSwapExtent = {0, 0}; -static VkImage g_vkDepthImage = VK_NULL_HANDLE; -static VkDeviceMemory g_vkDepthMemory = VK_NULL_HANDLE; -static VkImageView g_vkDepthImageView = VK_NULL_HANDLE; -static VkFormat g_vkDepthFormat = VK_FORMAT_UNDEFINED; -static VkBuffer g_vkDynamicVertexBuffer = VK_NULL_HANDLE; -static VkDeviceMemory g_vkDynamicVertexMemory = VK_NULL_HANDLE; -static size_t g_vkDynamicVertexCapacity = 0; -static bool g_vkDynamicVertexHostCoherent = true; -static uint8_t *g_vkDynamicVertexMapped = nullptr; -static VkBuffer g_vkUiStagingBuffer = VK_NULL_HANDLE; -static VkDeviceMemory g_vkUiStagingMemory = VK_NULL_HANDLE; -static size_t g_vkUiStagingCapacity = 0; -static bool g_vkUiStagingHostCoherent = true; -static uint8_t *g_vkUiStagingMapped = nullptr; -static VkImage g_vkUiImage = VK_NULL_HANDLE; -static VkDeviceMemory g_vkUiImageMemory = VK_NULL_HANDLE; -static VkImageView g_vkUiImageView = VK_NULL_HANDLE; -static VkSampler g_vkUiSampler = VK_NULL_HANDLE; -static VkImageLayout g_vkUiImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; -static uint32_t g_vkUiImageWidth = 0; -static uint32_t g_vkUiImageHeight = 0; -static bool g_vkUiImageReady = false; -static bool g_vkInitialized = false; -static int g_nextCommandBufferId = 1; -static int g_nextTextureId = 1; - -static const uint32_t kVertexStridePF3TF2CB4NB4XW1 = 32; -static const uint32_t kMaxTriangleTextureDescriptors = 4096; - -struct TrianglePushConstants { - float mvp[16]; - float alphaState[4]; // x=enable, y=ref, z=func, w=unused -}; - -struct VulkanTextureLevelData { - uint32_t width; - uint32_t height; - std::vector pixels; - bool valid; -}; - -struct VulkanTexture { - int id; - uint32_t width; - uint32_t height; - uint32_t mipLevels; - VkImage image; - VkDeviceMemory memory; - VkImageView imageView; - VkSampler sampler; - VkDescriptorSet descriptorSet; - VkImageLayout imageLayout; - int minFilter; - int magFilter; - int wrapS; - int wrapT; - uint32_t requestedMipLevels; - bool pendingUpload; - std::vector levelData; -}; - -static std::unordered_map g_vkTextures; -static VulkanTexture g_vkWhiteTexture = {}; -static bool g_vkWhiteTextureReady = false; - -struct VulkanQueuedDraw { - uint32_t firstVertex; - uint32_t vertexCount; - float mvp[16]; - bool depthTestEnable; - bool depthWriteEnable; - VkCompareOp depthCompareOp; - bool blendEnable; - VkBlendFactor srcBlendFactor; - VkBlendFactor dstBlendFactor; - VkColorComponentFlags colorWriteMask; - bool cullEnable; - bool cullClockwise; - float blendConstants[4]; - VkDescriptorSet descriptorSet; - bool alphaTestEnable; - int alphaFunc; - float alphaRef; -}; - -static std::vector g_vkFrameVertexData; -static std::vector g_vkQueuedDraws; -static bool g_vkShowCornerOverlay = true; -static bool g_vkShowPerfOverlay = true; -static LARGE_INTEGER g_vkPerfFreq = {}; -static LARGE_INTEGER g_vkPerfLastPresent = {}; -static float g_vkPerfFpsSmoothed = 0.0f; -static uint32_t g_vkPerfDrawCount = 0; -static uint32_t g_vkPerfVertexCount = 0; -static uint32_t g_vkPerfUploadBytes = 0; -static size_t g_vkFrameVertexReserveBytes = 1u << 20; -static size_t g_vkFrameDrawReserveCount = 4096; - -struct VulkanUiUploadFrame { - std::vector pixelsBGRA; - uint32_t width; - uint32_t height; - bool pending; -}; -static VulkanUiUploadFrame g_vkUiUpload = {}; - -static bool updateUiDescriptorSet(); -static void destroyAllTextures(bool preserveCpuCache); - -struct RecordedDrawCall { - C4JRender::ePrimitiveType primitiveType; - int count; - C4JRender::eVertexType vType; - C4JRender::ePixelShaderType psType; - std::vector vertexData; - // Pre-expanded to BootstrapVertex layout (RGBA + triangle list) for fast replay. - std::vector preparedVertexData; - uint32_t preparedVertexCount; - bool hasLocalModelMatrix; - float localModelMatrix[16]; - bool useCapturedState; - bool depthTestEnable; - bool depthWriteEnable; - VkCompareOp depthCompareOp; - bool blendEnable; - VkBlendFactor srcBlendFactor; - VkBlendFactor dstBlendFactor; - VkColorComponentFlags colorWriteMask; - bool cullEnable; - bool cullClockwise; - float blendConstants[4]; - // texture state is tracked separately; replay should not clobber runtime binds. - bool captureTextureState; - int textureId; - // same idea for alpha test state. - bool captureAlphaState; - bool alphaTestEnable; - int alphaFunc; - float alphaRef; -}; - -static std::unordered_map>> - g_vkCommandLists; -static std::mutex g_vkCommandListsMutex; -static thread_local bool g_vkIsRecordingCommandList = false; -static thread_local int g_vkRecordingCommandListIndex = -1; -static thread_local std::vector g_vkRecordingScratch; -static thread_local bool g_vkRecordingHasStateChanges = false; -static thread_local bool g_vkRecordingHasTextureStateChanges = false; -static thread_local bool g_vkRecordingHasAlphaStateChanges = false; -static thread_local bool g_vkRecordingBaseModelValid = false; -static thread_local float g_vkRecordingBaseModelInv[16]; - -struct BootstrapVertex { - float x, y, z; - float u, v; - uint8_t r, g, b, a; - uint8_t nx, ny, nz, nw; - uint32_t pad; -}; -static_assert(sizeof(BootstrapVertex) == kVertexStridePF3TF2CB4NB4XW1, - "BootstrapVertex must be 32 bytes."); - -static float g_clearColour[4] = {0.0f, 0.0f, 0.0f, 1.0f}; -static bool g_isWidescreen = true; -static thread_local bool g_vkStateDepthTestEnable = true; -static thread_local bool g_vkStateDepthWriteEnable = true; -static thread_local VkCompareOp g_vkStateDepthCompareOp = - VK_COMPARE_OP_LESS_OR_EQUAL; -static thread_local bool g_vkStateBlendEnable = false; -static thread_local VkBlendFactor g_vkStateSrcBlendFactor = VK_BLEND_FACTOR_ONE; -static thread_local VkBlendFactor g_vkStateDstBlendFactor = VK_BLEND_FACTOR_ZERO; -static thread_local bool g_vkStateCullEnable = false; -static thread_local bool g_vkStateCullClockwise = true; -static thread_local VkColorComponentFlags g_vkStateColorWriteMask = - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; -static thread_local float g_vkStateColour[4] = {1.0f, 1.0f, 1.0f, 1.0f}; -static thread_local float g_vkStateBlendConstants[4] = {1.0f, 1.0f, 1.0f, - 1.0f}; -static thread_local int g_vkStateTextureId = -1; -static thread_local int g_vkStateVertexTextureId = -1; -static thread_local bool g_vkStateAlphaTestEnable = false; -static thread_local int g_vkStateAlphaFunc = GL_ALWAYS; -static thread_local float g_vkStateAlphaRef = 0.0f; -static int g_vkPendingTextureLevels = 1; - -static void debugVk(const char *msg) { OutputDebugStringA(msg); } - -static bool getWindowClientSize(HWND hWnd, int &width, int &height) { - width = 0; - height = 0; - if (hWnd == NULL) - return false; - RECT rect = {}; - if (!GetClientRect(hWnd, &rect)) - return false; - width = rect.right - rect.left; - height = rect.bottom - rect.top; - return (width > 0 && height > 0); -} - -static void debugVkResult(const char *what, VkResult result) { - char buffer[256]; - std::snprintf(buffer, sizeof(buffer), "C4JRender_Vulkan: %s (VkResult=%d)\n", - what, (int)result); - OutputDebugStringA(buffer); -} - -static uint64_t makeTrianglePipelineKey(bool depthTestEnable, - bool depthWriteEnable, - VkCompareOp depthCompareOp, - bool blendEnable, - VkBlendFactor srcBlendFactor, - VkBlendFactor dstBlendFactor, - VkColorComponentFlags colorWriteMask, - bool cullEnable, - bool cullClockwise) { - uint64_t key = 0; - key |= (depthTestEnable ? 1ull : 0ull) << 0; - key |= (depthWriteEnable ? 1ull : 0ull) << 1; - key |= (blendEnable ? 1ull : 0ull) << 2; - key |= (cullEnable ? 1ull : 0ull) << 3; - key |= (cullClockwise ? 1ull : 0ull) << 4; - key |= (static_cast(depthCompareOp) & 0xffull) << 8; - key |= (static_cast(srcBlendFactor) & 0xffull) << 16; - key |= (static_cast(dstBlendFactor) & 0xffull) << 24; - key |= (static_cast(colorWriteMask) & 0xffull) << 32; - return key; -} - -static VkCompareOp mapDepthFuncToVk(int func) { - switch (func) { - case 1: - return VK_COMPARE_OP_NEVER; - case 2: - return VK_COMPARE_OP_LESS; - case 3: - return VK_COMPARE_OP_EQUAL; - case 4: - return VK_COMPARE_OP_LESS_OR_EQUAL; - case 5: - return VK_COMPARE_OP_GREATER; - case 6: - return VK_COMPARE_OP_NOT_EQUAL; - case 7: - return VK_COMPARE_OP_GREATER_OR_EQUAL; - case 8: - return VK_COMPARE_OP_ALWAYS; - default: - return VK_COMPARE_OP_LESS_OR_EQUAL; - } -} - -static VkBlendFactor mapBlendFactorToVk(int factor) { - switch (factor) { - case 1: - return VK_BLEND_FACTOR_ZERO; - case 2: - return VK_BLEND_FACTOR_ONE; - case 3: - return VK_BLEND_FACTOR_SRC_COLOR; - case 4: - return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; - case 5: - return VK_BLEND_FACTOR_SRC_ALPHA; - case 6: - return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - case 7: - return VK_BLEND_FACTOR_DST_ALPHA; - case 8: - return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; - case 9: - return VK_BLEND_FACTOR_DST_COLOR; - case 10: - return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR; - case 17: - return VK_BLEND_FACTOR_CONSTANT_ALPHA; - case 18: - return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA; - default: - return VK_BLEND_FACTOR_ONE; - } -} - -static void resetThreadLocalRenderState() { - g_vkStateDepthTestEnable = true; - g_vkStateDepthWriteEnable = true; - g_vkStateDepthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; - g_vkStateBlendEnable = false; - g_vkStateSrcBlendFactor = VK_BLEND_FACTOR_ONE; - g_vkStateDstBlendFactor = VK_BLEND_FACTOR_ZERO; - g_vkStateCullEnable = false; - g_vkStateCullClockwise = true; - g_vkStateColorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | - VK_COLOR_COMPONENT_A_BIT; - g_vkStateColour[0] = 1.0f; - g_vkStateColour[1] = 1.0f; - g_vkStateColour[2] = 1.0f; - g_vkStateColour[3] = 1.0f; - g_vkStateBlendConstants[0] = 1.0f; - g_vkStateBlendConstants[1] = 1.0f; - g_vkStateBlendConstants[2] = 1.0f; - g_vkStateBlendConstants[3] = 1.0f; - g_vkStateTextureId = -1; - g_vkStateVertexTextureId = -1; - g_vkStateAlphaTestEnable = false; - g_vkStateAlphaFunc = GL_ALWAYS; - g_vkStateAlphaRef = 0.0f; -} - -void VulkanSubmitIggyOverlayBGRA(int width, int height, const void *pixels, - size_t bytes) { - if (width <= 0 || height <= 0 || pixels == nullptr) - return; - const size_t expectedBytes = - static_cast(width) * static_cast(height) * 4u; - if (bytes < expectedBytes) - return; - - g_vkUiUpload.width = static_cast(width); - g_vkUiUpload.height = static_cast(height); - g_vkUiUpload.pixelsBGRA.resize(expectedBytes); - std::memcpy(g_vkUiUpload.pixelsBGRA.data(), pixels, expectedBytes); - g_vkUiUpload.pending = true; -} - -static bool hasValidationLayer(const char *layerName) { - uint32_t layerCount = 0; - VkResult res = vkEnumerateInstanceLayerProperties(&layerCount, nullptr); - if (res != VK_SUCCESS || layerCount == 0) - return false; - - std::vector props(layerCount); - res = vkEnumerateInstanceLayerProperties(&layerCount, props.data()); - if (res != VK_SUCCESS) - return false; - - for (const auto &p : props) { - if (std::strcmp(p.layerName, layerName) == 0) - return true; - } - return false; -} - -template static void SafeReleaseCOM(T *&p) { - if (p) { - p->Release(); - p = nullptr; - } -} - -static std::wstring toWidePath(const char *path) { - if (!path) - return std::wstring(); - - int len = MultiByteToWideChar(CP_UTF8, 0, path, -1, nullptr, 0); - UINT codePage = CP_UTF8; - if (len <= 0) { - codePage = CP_ACP; - len = MultiByteToWideChar(codePage, 0, path, -1, nullptr, 0); - } - if (len <= 0) - return std::wstring(); - - std::wstring out(len, L'\0'); - MultiByteToWideChar(codePage, 0, path, -1, &out[0], len); - if (!out.empty() && out.back() == L'\0') - out.pop_back(); - return out; -} - -static HRESULT decodeFrameToArgb(IWICBitmapFrameDecode *frame, - D3DXIMAGE_INFO *pSrcInfo, int **ppDataOut) { - if (!frame || !pSrcInfo || !ppDataOut) - return E_INVALIDARG; - - UINT width = 0; - UINT height = 0; - HRESULT hr = frame->GetSize(&width, &height); - if (FAILED(hr) || width == 0 || height == 0) - return FAILED(hr) ? hr : E_FAIL; - - IWICImagingFactory *factory = nullptr; - IWICFormatConverter *converter = nullptr; - hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, - IID_PPV_ARGS(&factory)); - if (FAILED(hr)) - return hr; - - hr = factory->CreateFormatConverter(&converter); - if (FAILED(hr)) { - SafeReleaseCOM(factory); - return hr; - } - - hr = converter->Initialize(frame, GUID_WICPixelFormat32bppBGRA, - WICBitmapDitherTypeNone, nullptr, 0.0f, - WICBitmapPaletteTypeCustom); - if (FAILED(hr)) { - SafeReleaseCOM(converter); - SafeReleaseCOM(factory); - return hr; - } - - const UINT stride = width * 4; - const UINT byteCount = stride * height; - std::vector pixels(byteCount); - hr = converter->CopyPixels(nullptr, stride, byteCount, pixels.data()); - if (FAILED(hr)) { - SafeReleaseCOM(converter); - SafeReleaseCOM(factory); - return hr; - } - - const size_t pixelCount = static_cast(width) * static_cast(height); - int *out = new int[pixelCount]; - for (size_t i = 0; i < pixelCount; ++i) { - const unsigned char b = pixels[i * 4 + 0]; - const unsigned char g = pixels[i * 4 + 1]; - const unsigned char r = pixels[i * 4 + 2]; - const unsigned char a = pixels[i * 4 + 3]; - out[i] = (static_cast(a) << 24) | (static_cast(r) << 16) | - (static_cast(g) << 8) | static_cast(b); - } - - pSrcInfo->Width = static_cast(width); - pSrcInfo->Height = static_cast(height); - *ppDataOut = out; - - SafeReleaseCOM(converter); - SafeReleaseCOM(factory); - return S_OK; -} - -static uint32_t findMemoryTypeIndex(uint32_t typeBits, - VkMemoryPropertyFlags requiredProperties, - bool &foundOut) { - foundOut = false; - if (g_vkPhysicalDevice == VK_NULL_HANDLE) - return 0; - - VkPhysicalDeviceMemoryProperties memProps = {}; - vkGetPhysicalDeviceMemoryProperties(g_vkPhysicalDevice, &memProps); - for (uint32_t i = 0; i < memProps.memoryTypeCount; ++i) { - if ((typeBits & (1u << i)) && - (memProps.memoryTypes[i].propertyFlags & requiredProperties) == - requiredProperties) { - foundOut = true; - return i; - } - } - return 0; -} - -static bool hasStencilComponent(VkFormat format) { - return format == VK_FORMAT_D24_UNORM_S8_UINT || - format == VK_FORMAT_D32_SFLOAT_S8_UINT; -} - -static VkFormat chooseDepthFormat() { - if (g_vkPhysicalDevice == VK_NULL_HANDLE) - return VK_FORMAT_UNDEFINED; - - const VkFormat candidates[] = { - VK_FORMAT_D32_SFLOAT, - VK_FORMAT_D24_UNORM_S8_UINT, - VK_FORMAT_D16_UNORM, - }; - - for (VkFormat format : candidates) { - VkFormatProperties props = {}; - vkGetPhysicalDeviceFormatProperties(g_vkPhysicalDevice, format, &props); - if (props.optimalTilingFeatures & - VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) { - return format; - } - } - return VK_FORMAT_UNDEFINED; -} - -static VkFilter mapTextureFilterToVk(int filter) { - return (filter == GL_NEAREST) ? VK_FILTER_NEAREST : VK_FILTER_LINEAR; -} - -static VkSamplerAddressMode mapTextureWrapToVk(int wrap) { - return (wrap == GL_REPEAT) ? VK_SAMPLER_ADDRESS_MODE_REPEAT - : VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; -} - -static bool hasTextureUploadContext() { - return g_vkInitialized && g_vkDevice != VK_NULL_HANDLE && - g_vkGraphicsQueue != VK_NULL_HANDLE && - g_vkCommandPool != VK_NULL_HANDLE && - g_vkTriangleDescriptorPool != VK_NULL_HANDLE && - g_vkTriangleDescriptorSetLayout != VK_NULL_HANDLE; -} - -static void cacheTextureLevelPixels(VulkanTexture &tex, uint32_t level, - uint32_t width, uint32_t height, - const void *data) { - if (data == nullptr || width == 0 || height == 0) - return; - if (tex.levelData.size() <= level) { - tex.levelData.resize(level + 1); - } - VulkanTextureLevelData &dst = tex.levelData[level]; - dst.width = width; - dst.height = height; - const size_t bytes = - static_cast(width) * static_cast(height) * 4u; - dst.pixels.resize(bytes); - std::memcpy(dst.pixels.data(), data, bytes); - dst.valid = true; - tex.pendingUpload = true; -} - -static bool patchTextureLevelPixels(VulkanTexture &tex, uint32_t level, - uint32_t xoffset, uint32_t yoffset, - uint32_t width, uint32_t height, - const void *data) { - if (data == nullptr || width == 0 || height == 0) - return false; - if (level >= tex.levelData.size()) - return false; - VulkanTextureLevelData &dst = tex.levelData[level]; - if (!dst.valid || dst.width == 0 || dst.height == 0) - return false; - if (xoffset + width > dst.width || yoffset + height > dst.height) - return false; - - const uint8_t *src = static_cast(data); - uint8_t *dstBase = dst.pixels.data(); - const size_t srcRowBytes = static_cast(width) * 4u; - const size_t dstRowBytes = static_cast(dst.width) * 4u; - for (uint32_t y = 0; y < height; ++y) { - uint8_t *dstRow = dstBase + - (static_cast(yoffset + y) * dstRowBytes) + - static_cast(xoffset) * 4u; - const uint8_t *srcRow = src + static_cast(y) * srcRowBytes; - std::memcpy(dstRow, srcRow, srcRowBytes); - } - tex.pendingUpload = true; - return true; -} - -static bool computeTextureDimensionsFromCache(const VulkanTexture &tex, - uint32_t &baseWidthOut, - uint32_t &baseHeightOut, - uint32_t &mipLevelsOut) { - bool haveAny = false; - uint32_t baseWidth = 0; - uint32_t baseHeight = 0; - uint32_t maxLevel = 0; - for (uint32_t level = 0; level < static_cast(tex.levelData.size()); - ++level) { - const VulkanTextureLevelData &ld = tex.levelData[level]; - if (!ld.valid || ld.width == 0 || ld.height == 0) - continue; - uint32_t candidateWidth = ld.width; - uint32_t candidateHeight = ld.height; - if (level > 0) { - candidateWidth <<= level; - candidateHeight <<= level; - } - if (!haveAny) { - baseWidth = candidateWidth; - baseHeight = candidateHeight; - haveAny = true; - } else { - if (candidateWidth > baseWidth) - baseWidth = candidateWidth; - if (candidateHeight > baseHeight) - baseHeight = candidateHeight; - } - if (level > maxLevel) - maxLevel = level; - } - if (!haveAny || baseWidth == 0 || baseHeight == 0) - return false; - - uint32_t levels = maxLevel + 1; - if (tex.requestedMipLevels > levels) - levels = tex.requestedMipLevels; - - baseWidthOut = baseWidth; - baseHeightOut = baseHeight; - mipLevelsOut = levels; - return true; -} - -static bool allocateTextureDescriptorSetIfNeeded(VulkanTexture &tex) { - if (tex.descriptorSet != VK_NULL_HANDLE) - return true; - if (g_vkDevice == VK_NULL_HANDLE || - g_vkTriangleDescriptorPool == VK_NULL_HANDLE || - g_vkTriangleDescriptorSetLayout == VK_NULL_HANDLE) - return false; - - VkDescriptorSetAllocateInfo dsAI = {}; - dsAI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - dsAI.descriptorPool = g_vkTriangleDescriptorPool; - dsAI.descriptorSetCount = 1; - dsAI.pSetLayouts = &g_vkTriangleDescriptorSetLayout; - VkResult result = vkAllocateDescriptorSets(g_vkDevice, &dsAI, &tex.descriptorSet); - if (result != VK_SUCCESS) { - debugVkResult("Failed to allocate triangle texture descriptor set", result); - tex.descriptorSet = VK_NULL_HANDLE; - return false; - } - return true; -} - -static bool updateTextureDescriptorSet(VulkanTexture &tex) { - if (!allocateTextureDescriptorSetIfNeeded(tex)) - return false; - if (g_vkDevice == VK_NULL_HANDLE || tex.descriptorSet == VK_NULL_HANDLE || - tex.imageView == VK_NULL_HANDLE || tex.sampler == VK_NULL_HANDLE || - tex.imageLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - return false; - } - - VkDescriptorImageInfo imageInfo = {}; - imageInfo.sampler = tex.sampler; - imageInfo.imageView = tex.imageView; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet write = {}; - write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write.dstSet = tex.descriptorSet; - write.dstBinding = 0; - write.dstArrayElement = 0; - write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - write.descriptorCount = 1; - write.pImageInfo = &imageInfo; - vkUpdateDescriptorSets(g_vkDevice, 1, &write, 0, nullptr); - return true; -} - -static void destroyTextureGpuResources(VulkanTexture &tex) { - if (g_vkDevice != VK_NULL_HANDLE && tex.descriptorSet != VK_NULL_HANDLE && - g_vkTriangleDescriptorPool != VK_NULL_HANDLE) { - vkFreeDescriptorSets(g_vkDevice, g_vkTriangleDescriptorPool, 1, - &tex.descriptorSet); - } - tex.descriptorSet = VK_NULL_HANDLE; - - if (g_vkDevice != VK_NULL_HANDLE && tex.sampler != VK_NULL_HANDLE) { - vkDestroySampler(g_vkDevice, tex.sampler, nullptr); - } - tex.sampler = VK_NULL_HANDLE; - - if (g_vkDevice != VK_NULL_HANDLE && tex.imageView != VK_NULL_HANDLE) { - vkDestroyImageView(g_vkDevice, tex.imageView, nullptr); - } - tex.imageView = VK_NULL_HANDLE; - - if (g_vkDevice != VK_NULL_HANDLE && tex.image != VK_NULL_HANDLE) { - vkDestroyImage(g_vkDevice, tex.image, nullptr); - } - tex.image = VK_NULL_HANDLE; - - if (g_vkDevice != VK_NULL_HANDLE && tex.memory != VK_NULL_HANDLE) { - vkFreeMemory(g_vkDevice, tex.memory, nullptr); - } - tex.memory = VK_NULL_HANDLE; - tex.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - tex.width = 0; - tex.height = 0; - tex.mipLevels = 1; -} - -static bool recreateTextureSampler(VulkanTexture &tex) { - if (g_vkDevice == VK_NULL_HANDLE) - return false; - - if (tex.sampler != VK_NULL_HANDLE) { - vkDestroySampler(g_vkDevice, tex.sampler, nullptr); - tex.sampler = VK_NULL_HANDLE; - } - - VkSamplerCreateInfo samplerCI = {}; - samplerCI.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - samplerCI.magFilter = mapTextureFilterToVk(tex.magFilter); - samplerCI.minFilter = mapTextureFilterToVk(tex.minFilter); - samplerCI.mipmapMode = - (tex.minFilter == GL_LINEAR) ? VK_SAMPLER_MIPMAP_MODE_LINEAR - : VK_SAMPLER_MIPMAP_MODE_NEAREST; - samplerCI.addressModeU = mapTextureWrapToVk(tex.wrapS); - samplerCI.addressModeV = mapTextureWrapToVk(tex.wrapT); - samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.mipLodBias = 0.0f; - samplerCI.anisotropyEnable = VK_FALSE; - samplerCI.maxAnisotropy = 1.0f; - samplerCI.compareEnable = VK_FALSE; - samplerCI.compareOp = VK_COMPARE_OP_ALWAYS; - samplerCI.minLod = 0.0f; - samplerCI.maxLod = (tex.mipLevels > 1) ? static_cast(tex.mipLevels - 1) - : 0.0f; - samplerCI.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; - samplerCI.unnormalizedCoordinates = VK_FALSE; - - VkResult result = vkCreateSampler(g_vkDevice, &samplerCI, nullptr, &tex.sampler); - if (result != VK_SUCCESS || tex.sampler == VK_NULL_HANDLE) { - debugVkResult("Failed to create texture sampler", result); - tex.sampler = VK_NULL_HANDLE; - return false; - } - - if (tex.imageView != VK_NULL_HANDLE && - tex.imageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - return updateTextureDescriptorSet(tex); - } - return true; -} - -static bool createTextureImageAndView(VulkanTexture &tex, uint32_t width, - uint32_t height, uint32_t mipLevels) { - if (g_vkDevice == VK_NULL_HANDLE || width == 0 || height == 0 || - mipLevels == 0) - return false; - - destroyTextureGpuResources(tex); - - VkImageCreateInfo imageCI = {}; - imageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = VK_FORMAT_R8G8B8A8_UNORM; - imageCI.extent = {width, height, 1}; - imageCI.mipLevels = mipLevels; - imageCI.arrayLayers = 1; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - imageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VkResult result = vkCreateImage(g_vkDevice, &imageCI, nullptr, &tex.image); - if (result != VK_SUCCESS || tex.image == VK_NULL_HANDLE) { - debugVkResult("Failed to create texture image", result); - destroyTextureGpuResources(tex); - return false; - } - - VkMemoryRequirements memReq = {}; - vkGetImageMemoryRequirements(g_vkDevice, tex.image, &memReq); - - bool foundMemory = false; - const uint32_t memoryTypeIndex = findMemoryTypeIndex( - memReq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, foundMemory); - if (!foundMemory) { - debugVk("C4JRender_Vulkan: No device-local memory type for texture image.\n"); - destroyTextureGpuResources(tex); - return false; - } - - VkMemoryAllocateInfo allocInfo = {}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memReq.size; - allocInfo.memoryTypeIndex = memoryTypeIndex; - result = vkAllocateMemory(g_vkDevice, &allocInfo, nullptr, &tex.memory); - if (result != VK_SUCCESS || tex.memory == VK_NULL_HANDLE) { - debugVkResult("Failed to allocate texture image memory", result); - destroyTextureGpuResources(tex); - return false; - } - - result = vkBindImageMemory(g_vkDevice, tex.image, tex.memory, 0); - if (result != VK_SUCCESS) { - debugVkResult("Failed to bind texture image memory", result); - destroyTextureGpuResources(tex); - return false; - } - - VkImageViewCreateInfo viewCI = {}; - viewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewCI.image = tex.image; - viewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewCI.format = VK_FORMAT_R8G8B8A8_UNORM; - viewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewCI.subresourceRange.baseMipLevel = 0; - viewCI.subresourceRange.levelCount = mipLevels; - viewCI.subresourceRange.baseArrayLayer = 0; - viewCI.subresourceRange.layerCount = 1; - result = vkCreateImageView(g_vkDevice, &viewCI, nullptr, &tex.imageView); - if (result != VK_SUCCESS || tex.imageView == VK_NULL_HANDLE) { - debugVkResult("Failed to create texture image view", result); - destroyTextureGpuResources(tex); - return false; - } - - tex.width = width; - tex.height = height; - tex.mipLevels = mipLevels; - tex.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - if (!recreateTextureSampler(tex)) - return false; - return true; -} - -static bool uploadTextureRegionImmediate(VulkanTexture &tex, uint32_t level, - uint32_t xoffset, uint32_t yoffset, - uint32_t width, uint32_t height, - const void *data); - -static bool ensureTextureUploadedFromCache(VulkanTexture &tex) { - if (!tex.pendingUpload) - return true; - if (!hasTextureUploadContext()) - return false; - - uint32_t baseWidth = 0; - uint32_t baseHeight = 0; - uint32_t mipLevels = 1; - if (!computeTextureDimensionsFromCache(tex, baseWidth, baseHeight, mipLevels)) - return false; - - const bool needsRecreate = (tex.image == VK_NULL_HANDLE) || - (tex.width != baseWidth) || - (tex.height != baseHeight) || - (tex.mipLevels != mipLevels); - if (needsRecreate) { - if (!createTextureImageAndView(tex, baseWidth, baseHeight, mipLevels)) - return false; - } - - for (uint32_t level = 0; level < static_cast(tex.levelData.size()); - ++level) { - const VulkanTextureLevelData &ld = tex.levelData[level]; - if (!ld.valid || ld.pixels.empty()) - continue; - if (level >= tex.mipLevels) - continue; - if (!uploadTextureRegionImmediate(tex, level, 0, 0, ld.width, ld.height, - ld.pixels.data())) { - return false; - } - } - - tex.pendingUpload = false; - return true; -} - -static void processPendingTextureUploads() { - if (!hasTextureUploadContext()) - return; - for (auto &kv : g_vkTextures) { - VulkanTexture &tex = kv.second; - if (tex.pendingUpload) { - ensureTextureUploadedFromCache(tex); - } - } -} - -static bool uploadTextureRegionImmediate(VulkanTexture &tex, uint32_t level, - uint32_t xoffset, uint32_t yoffset, - uint32_t width, uint32_t height, - const void *data) { - if (g_vkDevice == VK_NULL_HANDLE || g_vkGraphicsQueue == VK_NULL_HANDLE || - g_vkCommandPool == VK_NULL_HANDLE || tex.image == VK_NULL_HANDLE || - data == nullptr || width == 0 || height == 0 || - level >= tex.mipLevels) { - return false; - } - - const size_t uploadBytes = - static_cast(width) * static_cast(height) * 4u; - if (uploadBytes == 0) - return false; - - VkBuffer stagingBuffer = VK_NULL_HANDLE; - VkDeviceMemory stagingMemory = VK_NULL_HANDLE; - bool stagingHostCoherent = true; - - VkBufferCreateInfo bufCI = {}; - bufCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufCI.size = static_cast(uploadBytes); - bufCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - bufCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VkResult result = vkCreateBuffer(g_vkDevice, &bufCI, nullptr, &stagingBuffer); - if (result != VK_SUCCESS || stagingBuffer == VK_NULL_HANDLE) { - debugVkResult("Failed to create texture staging buffer", result); - return false; - } - - VkMemoryRequirements memReq = {}; - vkGetBufferMemoryRequirements(g_vkDevice, stagingBuffer, &memReq); - - bool foundMemory = false; - VkMemoryPropertyFlags memFlags = - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - uint32_t memoryTypeIndex = - findMemoryTypeIndex(memReq.memoryTypeBits, memFlags, foundMemory); - if (!foundMemory) { - memFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - memoryTypeIndex = - findMemoryTypeIndex(memReq.memoryTypeBits, memFlags, foundMemory); - stagingHostCoherent = false; - } - if (!foundMemory) { - debugVk("C4JRender_Vulkan: No host-visible memory type for texture staging.\n"); - vkDestroyBuffer(g_vkDevice, stagingBuffer, nullptr); - return false; - } - - VkMemoryAllocateInfo allocInfo = {}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memReq.size; - allocInfo.memoryTypeIndex = memoryTypeIndex; - result = vkAllocateMemory(g_vkDevice, &allocInfo, nullptr, &stagingMemory); - if (result != VK_SUCCESS || stagingMemory == VK_NULL_HANDLE) { - debugVkResult("Failed to allocate texture staging memory", result); - vkDestroyBuffer(g_vkDevice, stagingBuffer, nullptr); - return false; - } - - result = vkBindBufferMemory(g_vkDevice, stagingBuffer, stagingMemory, 0); - if (result != VK_SUCCESS) { - debugVkResult("Failed to bind texture staging memory", result); - vkFreeMemory(g_vkDevice, stagingMemory, nullptr); - vkDestroyBuffer(g_vkDevice, stagingBuffer, nullptr); - return false; - } - - void *mapped = nullptr; - result = vkMapMemory(g_vkDevice, stagingMemory, 0, uploadBytes, 0, &mapped); - if (result != VK_SUCCESS || mapped == nullptr) { - debugVkResult("Failed to map texture staging memory", result); - vkFreeMemory(g_vkDevice, stagingMemory, nullptr); - vkDestroyBuffer(g_vkDevice, stagingBuffer, nullptr); - return false; - } - std::memcpy(mapped, data, uploadBytes); - if (!stagingHostCoherent) { - VkMappedMemoryRange range = {}; - range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range.memory = stagingMemory; - range.offset = 0; - range.size = VK_WHOLE_SIZE; - result = vkFlushMappedMemoryRanges(g_vkDevice, 1, &range); - if (result != VK_SUCCESS) { - debugVkResult("Failed to flush texture staging memory", result); - vkUnmapMemory(g_vkDevice, stagingMemory); - vkFreeMemory(g_vkDevice, stagingMemory, nullptr); - vkDestroyBuffer(g_vkDevice, stagingBuffer, nullptr); - return false; - } - } - vkUnmapMemory(g_vkDevice, stagingMemory); - - VkCommandBuffer uploadCmd = VK_NULL_HANDLE; - VkCommandBufferAllocateInfo cbAI = {}; - cbAI.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - cbAI.commandPool = g_vkCommandPool; - cbAI.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - cbAI.commandBufferCount = 1; - result = vkAllocateCommandBuffers(g_vkDevice, &cbAI, &uploadCmd); - if (result != VK_SUCCESS || uploadCmd == VK_NULL_HANDLE) { - debugVkResult("Failed to allocate texture upload command buffer", result); - vkFreeMemory(g_vkDevice, stagingMemory, nullptr); - vkDestroyBuffer(g_vkDevice, stagingBuffer, nullptr); - return false; - } - - VkCommandBufferBeginInfo beginInfo = {}; - beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - result = vkBeginCommandBuffer(uploadCmd, &beginInfo); - if (result != VK_SUCCESS) { - debugVkResult("Failed to begin texture upload command buffer", result); - vkFreeCommandBuffers(g_vkDevice, g_vkCommandPool, 1, &uploadCmd); - vkFreeMemory(g_vkDevice, stagingMemory, nullptr); - vkDestroyBuffer(g_vkDevice, stagingBuffer, nullptr); - return false; - } - - VkImageMemoryBarrier toTransfer = {}; - toTransfer.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - toTransfer.oldLayout = tex.imageLayout; - toTransfer.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - toTransfer.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - toTransfer.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - toTransfer.image = tex.image; - toTransfer.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - toTransfer.subresourceRange.baseMipLevel = level; - toTransfer.subresourceRange.levelCount = 1; - toTransfer.subresourceRange.baseArrayLayer = 0; - toTransfer.subresourceRange.layerCount = 1; - - VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - if (tex.imageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - srcStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - toTransfer.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - } else if (tex.imageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { - srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - toTransfer.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - } else { - toTransfer.srcAccessMask = 0; - } - toTransfer.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - vkCmdPipelineBarrier(uploadCmd, srcStage, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, - nullptr, 0, nullptr, 1, &toTransfer); - - VkBufferImageCopy copyRegion = {}; - copyRegion.bufferOffset = 0; - copyRegion.bufferRowLength = 0; - copyRegion.bufferImageHeight = 0; - copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.imageSubresource.mipLevel = level; - copyRegion.imageSubresource.baseArrayLayer = 0; - copyRegion.imageSubresource.layerCount = 1; - copyRegion.imageOffset = {static_cast(xoffset), - static_cast(yoffset), 0}; - copyRegion.imageExtent = {width, height, 1}; - vkCmdCopyBufferToImage(uploadCmd, stagingBuffer, tex.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); - - VkImageMemoryBarrier toRead = {}; - toRead.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - toRead.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - toRead.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - toRead.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - toRead.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - toRead.image = tex.image; - toRead.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - toRead.subresourceRange.baseMipLevel = level; - toRead.subresourceRange.levelCount = 1; - toRead.subresourceRange.baseArrayLayer = 0; - toRead.subresourceRange.layerCount = 1; - toRead.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - toRead.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - vkCmdPipelineBarrier(uploadCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &toRead); - - result = vkEndCommandBuffer(uploadCmd); - if (result != VK_SUCCESS) { - debugVkResult("Failed to end texture upload command buffer", result); - vkFreeCommandBuffers(g_vkDevice, g_vkCommandPool, 1, &uploadCmd); - vkFreeMemory(g_vkDevice, stagingMemory, nullptr); - vkDestroyBuffer(g_vkDevice, stagingBuffer, nullptr); - return false; - } - - VkSubmitInfo submitInfo = {}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &uploadCmd; - result = vkQueueSubmit(g_vkGraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); - if (result != VK_SUCCESS) { - debugVkResult("Failed to submit texture upload", result); - vkFreeCommandBuffers(g_vkDevice, g_vkCommandPool, 1, &uploadCmd); - vkFreeMemory(g_vkDevice, stagingMemory, nullptr); - vkDestroyBuffer(g_vkDevice, stagingBuffer, nullptr); - return false; - } - - result = vkQueueWaitIdle(g_vkGraphicsQueue); - if (result != VK_SUCCESS) { - debugVkResult("Failed waiting for texture upload queue idle", result); - vkFreeCommandBuffers(g_vkDevice, g_vkCommandPool, 1, &uploadCmd); - vkFreeMemory(g_vkDevice, stagingMemory, nullptr); - vkDestroyBuffer(g_vkDevice, stagingBuffer, nullptr); - return false; - } - - vkFreeCommandBuffers(g_vkDevice, g_vkCommandPool, 1, &uploadCmd); - vkFreeMemory(g_vkDevice, stagingMemory, nullptr); - vkDestroyBuffer(g_vkDevice, stagingBuffer, nullptr); - - tex.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - updateTextureDescriptorSet(tex); - return true; -} - -static VkDescriptorSet resolveTextureDescriptorSet(int textureId) { - if (textureId >= 0) { - auto it = g_vkTextures.find(textureId); - if (it != g_vkTextures.end()) { - VulkanTexture &tex = it->second; - if (tex.pendingUpload) { - ensureTextureUploadedFromCache(tex); - } else if (tex.descriptorSet == VK_NULL_HANDLE && - tex.image != VK_NULL_HANDLE && hasTextureUploadContext()) { - updateTextureDescriptorSet(tex); - } - if (tex.descriptorSet != VK_NULL_HANDLE) { - return tex.descriptorSet; - } - } - } - if (g_vkWhiteTextureReady && - g_vkWhiteTexture.descriptorSet != VK_NULL_HANDLE) { - return g_vkWhiteTexture.descriptorSet; - } - return VK_NULL_HANDLE; -} - -static bool ensureWhiteTexture() { - if (g_vkWhiteTextureReady && - g_vkWhiteTexture.descriptorSet != VK_NULL_HANDLE) { - return true; - } - g_vkWhiteTexture.id = 0; - g_vkWhiteTexture.width = 0; - g_vkWhiteTexture.height = 0; - g_vkWhiteTexture.mipLevels = 1; - g_vkWhiteTexture.image = VK_NULL_HANDLE; - g_vkWhiteTexture.memory = VK_NULL_HANDLE; - g_vkWhiteTexture.imageView = VK_NULL_HANDLE; - g_vkWhiteTexture.sampler = VK_NULL_HANDLE; - g_vkWhiteTexture.descriptorSet = VK_NULL_HANDLE; - g_vkWhiteTexture.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - g_vkWhiteTexture.minFilter = GL_NEAREST; - g_vkWhiteTexture.magFilter = GL_NEAREST; - g_vkWhiteTexture.wrapS = GL_REPEAT; - g_vkWhiteTexture.wrapT = GL_REPEAT; - g_vkWhiteTexture.requestedMipLevels = 1; - g_vkWhiteTexture.pendingUpload = false; - g_vkWhiteTexture.levelData.clear(); - if (!createTextureImageAndView(g_vkWhiteTexture, 1, 1, 1)) - return false; - const uint8_t white[4] = {255, 255, 255, 255}; - if (!uploadTextureRegionImmediate(g_vkWhiteTexture, 0, 0, 0, 1, 1, white)) - return false; - g_vkWhiteTextureReady = true; - return true; -} - -static void destroyAllTextures(bool preserveCpuCache) { - for (auto it = g_vkTextures.begin(); it != g_vkTextures.end();) { - destroyTextureGpuResources(it->second); - if (preserveCpuCache) { - bool hasCachedData = false; - for (const auto &level : it->second.levelData) { - if (level.valid && !level.pixels.empty()) { - hasCachedData = true; - break; - } - } - it->second.pendingUpload = hasCachedData; - ++it; - } else { - it = g_vkTextures.erase(it); - } - } - destroyTextureGpuResources(g_vkWhiteTexture); - g_vkWhiteTexture = {}; - g_vkWhiteTextureReady = false; - if (!preserveCpuCache) { - g_vkPendingTextureLevels = 1; - } -} - -static void destroyDepthResources() { - if (g_vkDevice == VK_NULL_HANDLE) - return; - if (g_vkDepthImageView != VK_NULL_HANDLE) { - vkDestroyImageView(g_vkDevice, g_vkDepthImageView, nullptr); - g_vkDepthImageView = VK_NULL_HANDLE; - } - if (g_vkDepthImage != VK_NULL_HANDLE) { - vkDestroyImage(g_vkDevice, g_vkDepthImage, nullptr); - g_vkDepthImage = VK_NULL_HANDLE; - } - if (g_vkDepthMemory != VK_NULL_HANDLE) { - vkFreeMemory(g_vkDevice, g_vkDepthMemory, nullptr); - g_vkDepthMemory = VK_NULL_HANDLE; - } - g_vkDepthFormat = VK_FORMAT_UNDEFINED; -} - -static bool createDepthResources(uint32_t width, uint32_t height) { - if (g_vkDevice == VK_NULL_HANDLE || width == 0 || height == 0) - return false; - - destroyDepthResources(); - - g_vkDepthFormat = chooseDepthFormat(); - if (g_vkDepthFormat == VK_FORMAT_UNDEFINED) { - debugVk("C4JRender_Vulkan: No supported depth format.\n"); - return false; - } - - VkImageCreateInfo imageCI = {}; - imageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = g_vkDepthFormat; - imageCI.extent = {width, height, 1}; - imageCI.mipLevels = 1; - imageCI.arrayLayers = 1; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - imageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VkResult result = vkCreateImage(g_vkDevice, &imageCI, nullptr, &g_vkDepthImage); - if (result != VK_SUCCESS || g_vkDepthImage == VK_NULL_HANDLE) { - debugVkResult("Failed to create depth image", result); - destroyDepthResources(); - return false; - } - - VkMemoryRequirements memReq = {}; - vkGetImageMemoryRequirements(g_vkDevice, g_vkDepthImage, &memReq); - - bool found = false; - uint32_t memoryTypeIndex = findMemoryTypeIndex( - memReq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, found); - if (!found) { - debugVk("C4JRender_Vulkan: No device-local memory type for depth image.\n"); - destroyDepthResources(); - return false; - } - - VkMemoryAllocateInfo allocInfo = {}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memReq.size; - allocInfo.memoryTypeIndex = memoryTypeIndex; - result = vkAllocateMemory(g_vkDevice, &allocInfo, nullptr, &g_vkDepthMemory); - if (result != VK_SUCCESS || g_vkDepthMemory == VK_NULL_HANDLE) { - debugVkResult("Failed to allocate depth image memory", result); - destroyDepthResources(); - return false; - } - - result = vkBindImageMemory(g_vkDevice, g_vkDepthImage, g_vkDepthMemory, 0); - if (result != VK_SUCCESS) { - debugVkResult("Failed to bind depth image memory", result); - destroyDepthResources(); - return false; - } - - VkImageViewCreateInfo viewCI = {}; - viewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewCI.image = g_vkDepthImage; - viewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewCI.format = g_vkDepthFormat; - viewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (hasStencilComponent(g_vkDepthFormat)) - viewCI.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - viewCI.subresourceRange.baseMipLevel = 0; - viewCI.subresourceRange.levelCount = 1; - viewCI.subresourceRange.baseArrayLayer = 0; - viewCI.subresourceRange.layerCount = 1; - result = vkCreateImageView(g_vkDevice, &viewCI, nullptr, &g_vkDepthImageView); - if (result != VK_SUCCESS || g_vkDepthImageView == VK_NULL_HANDLE) { - debugVkResult("Failed to create depth image view", result); - destroyDepthResources(); - return false; - } - - return true; -} - -static void destroyDynamicVertexBuffer() { - if (g_vkDevice == VK_NULL_HANDLE) - return; - if (g_vkDynamicVertexMemory != VK_NULL_HANDLE && g_vkDynamicVertexMapped != nullptr) { - vkUnmapMemory(g_vkDevice, g_vkDynamicVertexMemory); - g_vkDynamicVertexMapped = nullptr; - } - if (g_vkDynamicVertexBuffer != VK_NULL_HANDLE) { - vkDestroyBuffer(g_vkDevice, g_vkDynamicVertexBuffer, nullptr); - g_vkDynamicVertexBuffer = VK_NULL_HANDLE; - } - if (g_vkDynamicVertexMemory != VK_NULL_HANDLE) { - vkFreeMemory(g_vkDevice, g_vkDynamicVertexMemory, nullptr); - g_vkDynamicVertexMemory = VK_NULL_HANDLE; - } - g_vkDynamicVertexCapacity = 0; - g_vkDynamicVertexHostCoherent = true; -} - -static bool ensureDynamicVertexBuffer(size_t minBytes) { - if (minBytes == 0) - return true; - if (g_vkDevice == VK_NULL_HANDLE) - return false; - if (g_vkDynamicVertexBuffer != VK_NULL_HANDLE && - g_vkDynamicVertexCapacity >= minBytes) { - return true; - } - - size_t newCapacity = 1u << 20; // 1MB default. - if (newCapacity < minBytes) - newCapacity = minBytes; - if (g_vkDynamicVertexCapacity > 0 && - newCapacity < g_vkDynamicVertexCapacity * 2) { - newCapacity = g_vkDynamicVertexCapacity * 2; - if (newCapacity < minBytes) - newCapacity = minBytes; - } - - destroyDynamicVertexBuffer(); - - VkBufferCreateInfo bufferCI = {}; - bufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferCI.size = static_cast(newCapacity); - bufferCI.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - bufferCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VkResult result = - vkCreateBuffer(g_vkDevice, &bufferCI, nullptr, &g_vkDynamicVertexBuffer); - if (result != VK_SUCCESS || g_vkDynamicVertexBuffer == VK_NULL_HANDLE) { - debugVkResult("Failed to create dynamic vertex buffer", result); - return false; - } - - VkMemoryRequirements memReq = {}; - vkGetBufferMemoryRequirements(g_vkDevice, g_vkDynamicVertexBuffer, &memReq); - - bool found = false; - uint32_t memoryTypeIndex = - findMemoryTypeIndex(memReq.memoryTypeBits, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - found); - g_vkDynamicVertexHostCoherent = true; - if (!found) { - memoryTypeIndex = findMemoryTypeIndex( - memReq.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, found); - g_vkDynamicVertexHostCoherent = false; - } - if (!found) { - debugVk("C4JRender_Vulkan: No host-visible memory type for vertex buffer.\n"); - destroyDynamicVertexBuffer(); - return false; - } - - VkMemoryAllocateInfo allocInfo = {}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memReq.size; - allocInfo.memoryTypeIndex = memoryTypeIndex; - result = vkAllocateMemory(g_vkDevice, &allocInfo, nullptr, &g_vkDynamicVertexMemory); - if (result != VK_SUCCESS || g_vkDynamicVertexMemory == VK_NULL_HANDLE) { - debugVkResult("Failed to allocate dynamic vertex buffer memory", result); - destroyDynamicVertexBuffer(); - return false; - } - - result = vkBindBufferMemory(g_vkDevice, g_vkDynamicVertexBuffer, - g_vkDynamicVertexMemory, 0); - if (result != VK_SUCCESS) { - debugVkResult("Failed to bind dynamic vertex buffer memory", result); - destroyDynamicVertexBuffer(); - return false; - } - - g_vkDynamicVertexCapacity = newCapacity; - void *mapped = nullptr; - result = vkMapMemory(g_vkDevice, g_vkDynamicVertexMemory, 0, VK_WHOLE_SIZE, 0, - &mapped); - if (result != VK_SUCCESS || mapped == nullptr) { - debugVkResult("Failed to map dynamic vertex buffer memory", result); - destroyDynamicVertexBuffer(); - return false; - } - g_vkDynamicVertexMapped = static_cast(mapped); - return true; -} - -static void destroyUiStagingBuffer() { - if (g_vkDevice == VK_NULL_HANDLE) - return; - if (g_vkUiStagingMemory != VK_NULL_HANDLE && g_vkUiStagingMapped != nullptr) { - vkUnmapMemory(g_vkDevice, g_vkUiStagingMemory); - g_vkUiStagingMapped = nullptr; - } - if (g_vkUiStagingBuffer != VK_NULL_HANDLE) { - vkDestroyBuffer(g_vkDevice, g_vkUiStagingBuffer, nullptr); - g_vkUiStagingBuffer = VK_NULL_HANDLE; - } - if (g_vkUiStagingMemory != VK_NULL_HANDLE) { - vkFreeMemory(g_vkDevice, g_vkUiStagingMemory, nullptr); - g_vkUiStagingMemory = VK_NULL_HANDLE; - } - g_vkUiStagingCapacity = 0; - g_vkUiStagingHostCoherent = true; -} - -static bool ensureUiStagingBuffer(size_t minBytes) { - if (minBytes == 0) - return true; - if (g_vkDevice == VK_NULL_HANDLE) - return false; - if (g_vkUiStagingBuffer != VK_NULL_HANDLE && g_vkUiStagingCapacity >= minBytes) - return true; - - size_t newCapacity = 1u << 20; // 1MB default. - if (newCapacity < minBytes) - newCapacity = minBytes; - - destroyUiStagingBuffer(); - - VkBufferCreateInfo bufferCI = {}; - bufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferCI.size = static_cast(newCapacity); - bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - bufferCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VkResult result = - vkCreateBuffer(g_vkDevice, &bufferCI, nullptr, &g_vkUiStagingBuffer); - if (result != VK_SUCCESS || g_vkUiStagingBuffer == VK_NULL_HANDLE) { - debugVkResult("Failed to create UI staging buffer", result); - return false; - } - - VkMemoryRequirements memReq = {}; - vkGetBufferMemoryRequirements(g_vkDevice, g_vkUiStagingBuffer, &memReq); - - bool found = false; - uint32_t memoryTypeIndex = - findMemoryTypeIndex(memReq.memoryTypeBits, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - found); - g_vkUiStagingHostCoherent = true; - if (!found) { - memoryTypeIndex = findMemoryTypeIndex( - memReq.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, found); - g_vkUiStagingHostCoherent = false; - } - if (!found) { - debugVk("C4JRender_Vulkan: No host-visible memory type for UI staging buffer.\n"); - destroyUiStagingBuffer(); - return false; - } - - VkMemoryAllocateInfo allocInfo = {}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memReq.size; - allocInfo.memoryTypeIndex = memoryTypeIndex; - result = vkAllocateMemory(g_vkDevice, &allocInfo, nullptr, &g_vkUiStagingMemory); - if (result != VK_SUCCESS || g_vkUiStagingMemory == VK_NULL_HANDLE) { - debugVkResult("Failed to allocate UI staging buffer memory", result); - destroyUiStagingBuffer(); - return false; - } - - result = - vkBindBufferMemory(g_vkDevice, g_vkUiStagingBuffer, g_vkUiStagingMemory, 0); - if (result != VK_SUCCESS) { - debugVkResult("Failed to bind UI staging buffer memory", result); - destroyUiStagingBuffer(); - return false; - } - - g_vkUiStagingCapacity = newCapacity; - void *mapped = nullptr; - result = vkMapMemory(g_vkDevice, g_vkUiStagingMemory, 0, VK_WHOLE_SIZE, 0, - &mapped); - if (result != VK_SUCCESS || mapped == nullptr) { - debugVkResult("Failed to map UI staging buffer memory", result); - destroyUiStagingBuffer(); - return false; - } - g_vkUiStagingMapped = static_cast(mapped); - return true; -} - -static void destroyUiImageResources() { - if (g_vkDevice == VK_NULL_HANDLE) - return; - if (g_vkUiSampler != VK_NULL_HANDLE) { - vkDestroySampler(g_vkDevice, g_vkUiSampler, nullptr); - g_vkUiSampler = VK_NULL_HANDLE; - } - if (g_vkUiImageView != VK_NULL_HANDLE) { - vkDestroyImageView(g_vkDevice, g_vkUiImageView, nullptr); - g_vkUiImageView = VK_NULL_HANDLE; - } - if (g_vkUiImage != VK_NULL_HANDLE) { - vkDestroyImage(g_vkDevice, g_vkUiImage, nullptr); - g_vkUiImage = VK_NULL_HANDLE; - } - if (g_vkUiImageMemory != VK_NULL_HANDLE) { - vkFreeMemory(g_vkDevice, g_vkUiImageMemory, nullptr); - g_vkUiImageMemory = VK_NULL_HANDLE; - } - g_vkUiImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - g_vkUiImageWidth = 0; - g_vkUiImageHeight = 0; - g_vkUiImageReady = false; -} - -static bool createOrResizeUiImageResources(uint32_t width, uint32_t height) { - if (width == 0 || height == 0 || g_vkDevice == VK_NULL_HANDLE) - return false; - - if (g_vkUiImage != VK_NULL_HANDLE && g_vkUiImageWidth == width && - g_vkUiImageHeight == height && g_vkUiImageView != VK_NULL_HANDLE && - g_vkUiSampler != VK_NULL_HANDLE) { - return true; - } - - destroyUiImageResources(); - - VkImageCreateInfo imageCI = {}; - imageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = VK_FORMAT_B8G8R8A8_UNORM; - imageCI.extent.width = width; - imageCI.extent.height = height; - imageCI.extent.depth = 1; - imageCI.mipLevels = 1; - imageCI.arrayLayers = 1; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - imageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkResult result = vkCreateImage(g_vkDevice, &imageCI, nullptr, &g_vkUiImage); - if (result != VK_SUCCESS || g_vkUiImage == VK_NULL_HANDLE) { - debugVkResult("Failed to create UI image", result); - return false; - } - - VkMemoryRequirements memReq = {}; - vkGetImageMemoryRequirements(g_vkDevice, g_vkUiImage, &memReq); - bool found = false; - uint32_t memoryTypeIndex = - findMemoryTypeIndex(memReq.memoryTypeBits, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, found); - if (!found) { - debugVk("C4JRender_Vulkan: No device-local memory type for UI image.\n"); - destroyUiImageResources(); - return false; - } - - VkMemoryAllocateInfo allocInfo = {}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memReq.size; - allocInfo.memoryTypeIndex = memoryTypeIndex; - result = vkAllocateMemory(g_vkDevice, &allocInfo, nullptr, &g_vkUiImageMemory); - if (result != VK_SUCCESS || g_vkUiImageMemory == VK_NULL_HANDLE) { - debugVkResult("Failed to allocate UI image memory", result); - destroyUiImageResources(); - return false; - } - - result = vkBindImageMemory(g_vkDevice, g_vkUiImage, g_vkUiImageMemory, 0); - if (result != VK_SUCCESS) { - debugVkResult("Failed to bind UI image memory", result); - destroyUiImageResources(); - return false; - } - - VkImageViewCreateInfo viewCI = {}; - viewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewCI.image = g_vkUiImage; - viewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewCI.format = VK_FORMAT_B8G8R8A8_UNORM; - viewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewCI.subresourceRange.baseMipLevel = 0; - viewCI.subresourceRange.levelCount = 1; - viewCI.subresourceRange.baseArrayLayer = 0; - viewCI.subresourceRange.layerCount = 1; - result = vkCreateImageView(g_vkDevice, &viewCI, nullptr, &g_vkUiImageView); - if (result != VK_SUCCESS || g_vkUiImageView == VK_NULL_HANDLE) { - debugVkResult("Failed to create UI image view", result); - destroyUiImageResources(); - return false; - } - - VkSamplerCreateInfo samplerCI = {}; - samplerCI.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - samplerCI.magFilter = VK_FILTER_LINEAR; - samplerCI.minFilter = VK_FILTER_LINEAR; - samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.minLod = 0.0f; - samplerCI.maxLod = 0.0f; - samplerCI.maxAnisotropy = 1.0f; - result = vkCreateSampler(g_vkDevice, &samplerCI, nullptr, &g_vkUiSampler); - if (result != VK_SUCCESS || g_vkUiSampler == VK_NULL_HANDLE) { - debugVkResult("Failed to create UI sampler", result); - destroyUiImageResources(); - return false; - } - - g_vkUiImageWidth = width; - g_vkUiImageHeight = height; - g_vkUiImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - g_vkUiImageReady = false; - return true; -} - -static void destroySwapchainDrawResources() { - if (g_vkDevice != VK_NULL_HANDLE) { - for (VkFramebuffer fb : g_vkFramebuffers) { - if (fb != VK_NULL_HANDLE) - vkDestroyFramebuffer(g_vkDevice, fb, nullptr); - } - g_vkFramebuffers.clear(); - - for (auto &kv : g_vkTrianglePipelines) { - if (kv.second != VK_NULL_HANDLE) - vkDestroyPipeline(g_vkDevice, kv.second, nullptr); - } - g_vkTrianglePipelines.clear(); - g_vkTrianglePipeline = VK_NULL_HANDLE; - if (g_vkUiPipeline != VK_NULL_HANDLE) { - vkDestroyPipeline(g_vkDevice, g_vkUiPipeline, nullptr); - g_vkUiPipeline = VK_NULL_HANDLE; - } - if (g_vkPipelineLayout != VK_NULL_HANDLE) { - vkDestroyPipelineLayout(g_vkDevice, g_vkPipelineLayout, nullptr); - g_vkPipelineLayout = VK_NULL_HANDLE; - } - if (g_vkTriangleDescriptorPool != VK_NULL_HANDLE) { - vkDestroyDescriptorPool(g_vkDevice, g_vkTriangleDescriptorPool, nullptr); - g_vkTriangleDescriptorPool = VK_NULL_HANDLE; - } - for (auto &kv : g_vkTextures) { - kv.second.descriptorSet = VK_NULL_HANDLE; - } - g_vkWhiteTexture.descriptorSet = VK_NULL_HANDLE; - if (g_vkTriangleDescriptorSetLayout != VK_NULL_HANDLE) { - vkDestroyDescriptorSetLayout(g_vkDevice, g_vkTriangleDescriptorSetLayout, - nullptr); - g_vkTriangleDescriptorSetLayout = VK_NULL_HANDLE; - } - g_vkWhiteTextureReady = false; - if (g_vkUiPipelineLayout != VK_NULL_HANDLE) { - vkDestroyPipelineLayout(g_vkDevice, g_vkUiPipelineLayout, nullptr); - g_vkUiPipelineLayout = VK_NULL_HANDLE; - } - if (g_vkUiDescriptorPool != VK_NULL_HANDLE) { - vkDestroyDescriptorPool(g_vkDevice, g_vkUiDescriptorPool, nullptr); - g_vkUiDescriptorPool = VK_NULL_HANDLE; - } - if (g_vkUiDescriptorSetLayout != VK_NULL_HANDLE) { - vkDestroyDescriptorSetLayout(g_vkDevice, g_vkUiDescriptorSetLayout, - nullptr); - g_vkUiDescriptorSetLayout = VK_NULL_HANDLE; - } - g_vkUiDescriptorSet = VK_NULL_HANDLE; - if (g_vkRenderPass != VK_NULL_HANDLE) { - vkDestroyRenderPass(g_vkDevice, g_vkRenderPass, nullptr); - g_vkRenderPass = VK_NULL_HANDLE; - } - destroyDepthResources(); - - for (VkImageView view : g_vkSwapImageViews) { - if (view != VK_NULL_HANDLE) - vkDestroyImageView(g_vkDevice, view, nullptr); - } - } - g_vkSwapImageViews.clear(); -} - -static void destroyVulkanRuntime() { - if (g_vkDevice != VK_NULL_HANDLE) - vkDeviceWaitIdle(g_vkDevice); - - destroyAllTextures(true); - destroySwapchainDrawResources(); - destroyDynamicVertexBuffer(); - destroyUiStagingBuffer(); - destroyUiImageResources(); - - if (g_vkDevice != VK_NULL_HANDLE) { - if (g_vkImageAvailable != VK_NULL_HANDLE) { - vkDestroySemaphore(g_vkDevice, g_vkImageAvailable, nullptr); - g_vkImageAvailable = VK_NULL_HANDLE; - } - if (g_vkRenderFinished != VK_NULL_HANDLE) { - vkDestroySemaphore(g_vkDevice, g_vkRenderFinished, nullptr); - g_vkRenderFinished = VK_NULL_HANDLE; - } - if (g_vkFence != VK_NULL_HANDLE) { - vkDestroyFence(g_vkDevice, g_vkFence, nullptr); - g_vkFence = VK_NULL_HANDLE; - } - if (g_vkCommandPool != VK_NULL_HANDLE) { - vkDestroyCommandPool(g_vkDevice, g_vkCommandPool, nullptr); - g_vkCommandPool = VK_NULL_HANDLE; - g_vkCommandBuffer = VK_NULL_HANDLE; - } - if (g_vkSwapchain != VK_NULL_HANDLE) { - vkDestroySwapchainKHR(g_vkDevice, g_vkSwapchain, nullptr); - g_vkSwapchain = VK_NULL_HANDLE; - } - vkDestroyDevice(g_vkDevice, nullptr); - g_vkDevice = VK_NULL_HANDLE; - g_vkGraphicsQueue = VK_NULL_HANDLE; - } - - if (g_vkSurface != VK_NULL_HANDLE) { - vkDestroySurfaceKHR(g_vkInstance, g_vkSurface, nullptr); - g_vkSurface = VK_NULL_HANDLE; - } - if (g_vkInstance != VK_NULL_HANDLE) { - vkDestroyInstance(g_vkInstance, nullptr); - g_vkInstance = VK_NULL_HANDLE; - } - - g_vkPhysicalDevice = VK_NULL_HANDLE; - g_vkGraphicsFamily = 0; - g_vkSwapImages.clear(); - g_vkSwapImageLayouts.clear(); - g_vkFrameVertexData.clear(); - g_vkQueuedDraws.clear(); - { - std::lock_guard commandListsLock(g_vkCommandListsMutex); - g_vkCommandLists.clear(); - } - g_vkIsRecordingCommandList = false; - g_vkRecordingCommandListIndex = -1; - g_vkSwapExtent = {0, 0}; - g_vkUiUpload.pixelsBGRA.clear(); - g_vkUiUpload.width = 0; - g_vkUiUpload.height = 0; - g_vkUiUpload.pending = false; - resetThreadLocalRenderState(); - g_vkRecordingHasStateChanges = false; - g_vkRecordingHasTextureStateChanges = false; - g_vkRecordingHasAlphaStateChanges = false; - g_vkInitialized = false; -} - -static VkShaderModule createShaderModule(const uint32_t *code, - size_t codeWordCount) { - if (g_vkDevice == VK_NULL_HANDLE || !code || codeWordCount == 0) - return VK_NULL_HANDLE; - - VkShaderModuleCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.codeSize = codeWordCount * sizeof(uint32_t); - createInfo.pCode = code; - - VkShaderModule module = VK_NULL_HANDLE; - VkResult result = vkCreateShaderModule(g_vkDevice, &createInfo, nullptr, &module); - if (result != VK_SUCCESS) { - debugVkResult("Failed to create shader module", result); - return VK_NULL_HANDLE; - } - return module; -} - -static VkPipeline createTrianglePipeline(bool depthTestEnable, - bool depthWriteEnable, - VkCompareOp depthCompareOp, - bool blendEnable, - VkBlendFactor srcBlendFactor, - VkBlendFactor dstBlendFactor, - VkColorComponentFlags colorWriteMask, - bool cullEnable, - bool cullClockwise) { - if (g_vkDevice == VK_NULL_HANDLE || g_vkRenderPass == VK_NULL_HANDLE || - g_vkPipelineLayout == VK_NULL_HANDLE) - return VK_NULL_HANDLE; - - VkShaderModule vertModule = - createShaderModule(kTriangleVertSpv, - sizeof(kTriangleVertSpv) / sizeof(kTriangleVertSpv[0])); - VkShaderModule fragModule = - createShaderModule(kTriangleFragSpv, - sizeof(kTriangleFragSpv) / sizeof(kTriangleFragSpv[0])); - if (vertModule == VK_NULL_HANDLE || fragModule == VK_NULL_HANDLE) { - if (vertModule != VK_NULL_HANDLE) - vkDestroyShaderModule(g_vkDevice, vertModule, nullptr); - if (fragModule != VK_NULL_HANDLE) - vkDestroyShaderModule(g_vkDevice, fragModule, nullptr); - return VK_NULL_HANDLE; - } - - VkPipelineShaderStageCreateInfo stages[2] = {}; - stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - stages[0].module = vertModule; - stages[0].pName = "main"; - stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - stages[1].module = fragModule; - stages[1].pName = "main"; - - VkVertexInputBindingDescription bindingDesc = {}; - bindingDesc.binding = 0; - bindingDesc.stride = kVertexStridePF3TF2CB4NB4XW1; - bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - VkVertexInputAttributeDescription attribs[3] = {}; - attribs[0].location = 0; - attribs[0].binding = 0; - attribs[0].format = VK_FORMAT_R32G32B32_SFLOAT; - attribs[0].offset = 0; - attribs[1].location = 1; - attribs[1].binding = 0; - attribs[1].format = VK_FORMAT_R32G32_SFLOAT; - attribs[1].offset = 12; - attribs[2].location = 2; - attribs[2].binding = 0; - attribs[2].format = VK_FORMAT_R8G8B8A8_UNORM; - attribs[2].offset = 20; - - VkPipelineVertexInputStateCreateInfo viState = {}; - viState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - viState.vertexBindingDescriptionCount = 1; - viState.pVertexBindingDescriptions = &bindingDesc; - viState.vertexAttributeDescriptionCount = 3; - viState.pVertexAttributeDescriptions = attribs; - - VkPipelineInputAssemblyStateCreateInfo iaState = {}; - iaState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - iaState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - iaState.primitiveRestartEnable = VK_FALSE; - - VkViewport viewport = {}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = static_cast(g_vkSwapExtent.width); - viewport.height = static_cast(g_vkSwapExtent.height); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor = {}; - scissor.offset = {0, 0}; - scissor.extent = g_vkSwapExtent; - - VkPipelineViewportStateCreateInfo vpState = {}; - vpState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - vpState.viewportCount = 1; - vpState.pViewports = &viewport; - vpState.scissorCount = 1; - vpState.pScissors = &scissor; - - VkPipelineRasterizationStateCreateInfo rsState = {}; - rsState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rsState.depthClampEnable = VK_FALSE; - rsState.rasterizerDiscardEnable = VK_FALSE; - rsState.polygonMode = VK_POLYGON_MODE_FILL; - rsState.cullMode = cullEnable ? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_NONE; - rsState.frontFace = - cullClockwise ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE; - rsState.depthBiasEnable = VK_FALSE; - rsState.lineWidth = 1.0f; - - VkPipelineMultisampleStateCreateInfo msState = {}; - msState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - msState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - - VkPipelineColorBlendAttachmentState blendAttachment = {}; - blendAttachment.blendEnable = blendEnable ? VK_TRUE : VK_FALSE; - blendAttachment.srcColorBlendFactor = srcBlendFactor; - blendAttachment.dstColorBlendFactor = dstBlendFactor; - blendAttachment.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachment.srcAlphaBlendFactor = srcBlendFactor; - blendAttachment.dstAlphaBlendFactor = dstBlendFactor; - blendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; - blendAttachment.colorWriteMask = colorWriteMask; - - VkPipelineColorBlendStateCreateInfo cbState = {}; - cbState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - cbState.attachmentCount = 1; - cbState.pAttachments = &blendAttachment; - - VkPipelineDepthStencilStateCreateInfo depthState = {}; - depthState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depthState.depthTestEnable = depthTestEnable ? VK_TRUE : VK_FALSE; - depthState.depthWriteEnable = depthWriteEnable ? VK_TRUE : VK_FALSE; - depthState.depthCompareOp = depthCompareOp; - depthState.depthBoundsTestEnable = VK_FALSE; - depthState.stencilTestEnable = VK_FALSE; - - VkGraphicsPipelineCreateInfo gpCI = {}; - gpCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - gpCI.stageCount = 2; - gpCI.pStages = stages; - gpCI.pVertexInputState = &viState; - gpCI.pInputAssemblyState = &iaState; - gpCI.pViewportState = &vpState; - gpCI.pRasterizationState = &rsState; - gpCI.pMultisampleState = &msState; - gpCI.pDepthStencilState = &depthState; - gpCI.pColorBlendState = &cbState; - gpCI.layout = g_vkPipelineLayout; - gpCI.renderPass = g_vkRenderPass; - gpCI.subpass = 0; - - VkPipeline pipeline = VK_NULL_HANDLE; - VkResult result = - vkCreateGraphicsPipelines(g_vkDevice, VK_NULL_HANDLE, 1, &gpCI, nullptr, - &pipeline); - vkDestroyShaderModule(g_vkDevice, vertModule, nullptr); - vkDestroyShaderModule(g_vkDevice, fragModule, nullptr); - if (result != VK_SUCCESS || pipeline == VK_NULL_HANDLE) { - debugVkResult("Failed to create triangle graphics pipeline", result); - return VK_NULL_HANDLE; - } - return pipeline; -} - -static VkPipeline getOrCreateTrianglePipeline(bool depthTestEnable, - bool depthWriteEnable, - VkCompareOp depthCompareOp, - bool blendEnable, - VkBlendFactor srcBlendFactor, - VkBlendFactor dstBlendFactor, - VkColorComponentFlags colorWriteMask, - bool cullEnable, - bool cullClockwise) { - const uint64_t key = - makeTrianglePipelineKey(depthTestEnable, depthWriteEnable, depthCompareOp, - blendEnable, srcBlendFactor, dstBlendFactor, - colorWriteMask, cullEnable, cullClockwise); - auto it = g_vkTrianglePipelines.find(key); - if (it != g_vkTrianglePipelines.end()) - return it->second; - - VkPipeline pipeline = createTrianglePipeline( - depthTestEnable, depthWriteEnable, depthCompareOp, blendEnable, - srcBlendFactor, dstBlendFactor, colorWriteMask, cullEnable, - cullClockwise); - if (pipeline == VK_NULL_HANDLE) - return VK_NULL_HANDLE; - g_vkTrianglePipelines[key] = pipeline; - return pipeline; -} - -static bool createTriangleRenderResources() { - if (g_vkDevice == VK_NULL_HANDLE || g_vkSwapImages.empty()) - return false; - if (g_vkSwapExtent.width == 0 || g_vkSwapExtent.height == 0) - return false; - - destroySwapchainDrawResources(); - - g_vkSwapImageViews.assign(g_vkSwapImages.size(), VK_NULL_HANDLE); - for (size_t i = 0; i < g_vkSwapImages.size(); ++i) { - VkImageViewCreateInfo ivCI = {}; - ivCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivCI.image = g_vkSwapImages[i]; - ivCI.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivCI.format = g_vkSwapFormat; - ivCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - ivCI.subresourceRange.baseMipLevel = 0; - ivCI.subresourceRange.levelCount = 1; - ivCI.subresourceRange.baseArrayLayer = 0; - ivCI.subresourceRange.layerCount = 1; - - VkResult result = - vkCreateImageView(g_vkDevice, &ivCI, nullptr, &g_vkSwapImageViews[i]); - if (result != VK_SUCCESS) { - debugVkResult("Failed to create swapchain image view", result); - return false; - } - } - if (!createDepthResources(g_vkSwapExtent.width, g_vkSwapExtent.height)) - return false; - - VkAttachmentDescription colorAttachment = {}; - colorAttachment.format = g_vkSwapFormat; - colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - colorAttachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentDescription depthAttachment = {}; - depthAttachment.format = g_vkDepthFormat; - depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT; - depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference colorAttachmentRef = {}; - colorAttachmentRef.attachment = 0; - colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkAttachmentReference depthAttachmentRef = {}; - depthAttachmentRef.attachment = 1; - depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentDescription attachments[2] = {colorAttachment, depthAttachment}; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorAttachmentRef; - subpass.pDepthStencilAttachment = &depthAttachmentRef; - - VkSubpassDependency dependency = {}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependency.srcAccessMask = 0; - dependency.dstAccessMask = - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - - VkRenderPassCreateInfo rpCI = {}; - rpCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - rpCI.attachmentCount = 2; - rpCI.pAttachments = attachments; - rpCI.subpassCount = 1; - rpCI.pSubpasses = &subpass; - rpCI.dependencyCount = 1; - rpCI.pDependencies = &dependency; - VkResult result = vkCreateRenderPass(g_vkDevice, &rpCI, nullptr, &g_vkRenderPass); - if (result != VK_SUCCESS) { - debugVkResult("Failed to create render pass", result); - return false; - } - - VkDescriptorSetLayoutBinding triangleSamplerBinding = {}; - triangleSamplerBinding.binding = 0; - triangleSamplerBinding.descriptorType = - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - triangleSamplerBinding.descriptorCount = 1; - triangleSamplerBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - triangleSamplerBinding.pImmutableSamplers = nullptr; - - VkDescriptorSetLayoutCreateInfo triangleDslCI = {}; - triangleDslCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - triangleDslCI.bindingCount = 1; - triangleDslCI.pBindings = &triangleSamplerBinding; - result = vkCreateDescriptorSetLayout(g_vkDevice, &triangleDslCI, nullptr, - &g_vkTriangleDescriptorSetLayout); - if (result != VK_SUCCESS || - g_vkTriangleDescriptorSetLayout == VK_NULL_HANDLE) { - debugVkResult("Failed to create triangle descriptor set layout", result); - return false; - } - - VkDescriptorPoolSize trianglePoolSize = {}; - trianglePoolSize.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - trianglePoolSize.descriptorCount = kMaxTriangleTextureDescriptors; - - VkDescriptorPoolCreateInfo triangleDpCI = {}; - triangleDpCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - triangleDpCI.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - triangleDpCI.maxSets = kMaxTriangleTextureDescriptors; - triangleDpCI.poolSizeCount = 1; - triangleDpCI.pPoolSizes = &trianglePoolSize; - result = vkCreateDescriptorPool(g_vkDevice, &triangleDpCI, nullptr, - &g_vkTriangleDescriptorPool); - if (result != VK_SUCCESS || g_vkTriangleDescriptorPool == VK_NULL_HANDLE) { - debugVkResult("Failed to create triangle descriptor pool", result); - return false; - } - - VkPipelineLayoutCreateInfo plCI = {}; - plCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - plCI.setLayoutCount = 1; - plCI.pSetLayouts = &g_vkTriangleDescriptorSetLayout; - VkPushConstantRange trianglePushRange = {}; - trianglePushRange.stageFlags = - VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; - trianglePushRange.offset = 0; - trianglePushRange.size = sizeof(TrianglePushConstants); - plCI.pushConstantRangeCount = 1; - plCI.pPushConstantRanges = &trianglePushRange; - result = vkCreatePipelineLayout(g_vkDevice, &plCI, nullptr, &g_vkPipelineLayout); - if (result != VK_SUCCESS) { - debugVkResult("Failed to create pipeline layout", result); - return false; - } - - g_vkTrianglePipelines.clear(); - g_vkTrianglePipeline = createTrianglePipeline( - true, true, VK_COMPARE_OP_LESS_OR_EQUAL, false, VK_BLEND_FACTOR_ONE, - VK_BLEND_FACTOR_ZERO, - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, - false, true); - if (g_vkTrianglePipeline == VK_NULL_HANDLE) - return false; - g_vkTrianglePipelines[makeTrianglePipelineKey( - true, true, VK_COMPARE_OP_LESS_OR_EQUAL, false, VK_BLEND_FACTOR_ONE, - VK_BLEND_FACTOR_ZERO, - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, - false, true)] = g_vkTrianglePipeline; - - VkVertexInputBindingDescription bindingDesc = {}; - bindingDesc.binding = 0; - bindingDesc.stride = kVertexStridePF3TF2CB4NB4XW1; - bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - VkVertexInputAttributeDescription attribs[3] = {}; - attribs[0].location = 0; - attribs[0].binding = 0; - attribs[0].format = VK_FORMAT_R32G32B32_SFLOAT; - attribs[0].offset = 0; - attribs[1].location = 1; - attribs[1].binding = 0; - attribs[1].format = VK_FORMAT_R32G32_SFLOAT; - attribs[1].offset = 12; - attribs[2].location = 2; - attribs[2].binding = 0; - attribs[2].format = VK_FORMAT_R8G8B8A8_UNORM; - attribs[2].offset = 20; - - VkPipelineVertexInputStateCreateInfo viState = {}; - viState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - viState.vertexBindingDescriptionCount = 1; - viState.pVertexBindingDescriptions = &bindingDesc; - viState.vertexAttributeDescriptionCount = 3; - viState.pVertexAttributeDescriptions = attribs; - - VkPipelineInputAssemblyStateCreateInfo iaState = {}; - iaState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - iaState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - iaState.primitiveRestartEnable = VK_FALSE; - - VkViewport viewport = {}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = static_cast(g_vkSwapExtent.width); - viewport.height = static_cast(g_vkSwapExtent.height); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor = {}; - scissor.offset = {0, 0}; - scissor.extent = g_vkSwapExtent; - - VkPipelineViewportStateCreateInfo vpState = {}; - vpState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - vpState.viewportCount = 1; - vpState.pViewports = &viewport; - vpState.scissorCount = 1; - vpState.pScissors = &scissor; - - VkPipelineRasterizationStateCreateInfo rsState = {}; - rsState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rsState.depthClampEnable = VK_FALSE; - rsState.rasterizerDiscardEnable = VK_FALSE; - rsState.polygonMode = VK_POLYGON_MODE_FILL; - rsState.cullMode = VK_CULL_MODE_NONE; - rsState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rsState.depthBiasEnable = VK_FALSE; - rsState.lineWidth = 1.0f; - - VkPipelineMultisampleStateCreateInfo msState = {}; - msState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - msState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - - VkDescriptorSetLayoutBinding samplerBinding = {}; - samplerBinding.binding = 0; - samplerBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - samplerBinding.descriptorCount = 1; - samplerBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - samplerBinding.pImmutableSamplers = nullptr; - - VkDescriptorSetLayoutCreateInfo dslCI = {}; - dslCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - dslCI.bindingCount = 1; - dslCI.pBindings = &samplerBinding; - result = vkCreateDescriptorSetLayout(g_vkDevice, &dslCI, nullptr, - &g_vkUiDescriptorSetLayout); - if (result != VK_SUCCESS || g_vkUiDescriptorSetLayout == VK_NULL_HANDLE) { - debugVkResult("Failed to create UI descriptor set layout", result); - return false; - } - - VkDescriptorPoolSize poolSize = {}; - poolSize.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - poolSize.descriptorCount = 1; - - VkDescriptorPoolCreateInfo dpCI = {}; - dpCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - dpCI.maxSets = 1; - dpCI.poolSizeCount = 1; - dpCI.pPoolSizes = &poolSize; - result = vkCreateDescriptorPool(g_vkDevice, &dpCI, nullptr, - &g_vkUiDescriptorPool); - if (result != VK_SUCCESS || g_vkUiDescriptorPool == VK_NULL_HANDLE) { - debugVkResult("Failed to create UI descriptor pool", result); - return false; - } - - VkDescriptorSetAllocateInfo dsAI = {}; - dsAI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - dsAI.descriptorPool = g_vkUiDescriptorPool; - dsAI.descriptorSetCount = 1; - dsAI.pSetLayouts = &g_vkUiDescriptorSetLayout; - result = vkAllocateDescriptorSets(g_vkDevice, &dsAI, &g_vkUiDescriptorSet); - if (result != VK_SUCCESS || g_vkUiDescriptorSet == VK_NULL_HANDLE) { - debugVkResult("Failed to allocate UI descriptor set", result); - return false; - } - - VkPipelineLayoutCreateInfo uiPlCI = {}; - uiPlCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - uiPlCI.setLayoutCount = 1; - uiPlCI.pSetLayouts = &g_vkUiDescriptorSetLayout; - VkPushConstantRange uiPushRange = {}; - uiPushRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - uiPushRange.offset = 0; - uiPushRange.size = sizeof(float) * 16; - uiPlCI.pushConstantRangeCount = 1; - uiPlCI.pPushConstantRanges = &uiPushRange; - result = vkCreatePipelineLayout(g_vkDevice, &uiPlCI, nullptr, - &g_vkUiPipelineLayout); - if (result != VK_SUCCESS || g_vkUiPipelineLayout == VK_NULL_HANDLE) { - debugVkResult("Failed to create UI pipeline layout", result); - return false; - } - - VkShaderModule uiVertModule = - createShaderModule(kUiCompositeVertSpv, - sizeof(kUiCompositeVertSpv) / sizeof(kUiCompositeVertSpv[0])); - VkShaderModule uiFragModule = - createShaderModule(kUiCompositeFragSpv, - sizeof(kUiCompositeFragSpv) / sizeof(kUiCompositeFragSpv[0])); - if (uiVertModule == VK_NULL_HANDLE || uiFragModule == VK_NULL_HANDLE) { - if (uiVertModule != VK_NULL_HANDLE) - vkDestroyShaderModule(g_vkDevice, uiVertModule, nullptr); - if (uiFragModule != VK_NULL_HANDLE) - vkDestroyShaderModule(g_vkDevice, uiFragModule, nullptr); - return false; - } - - VkPipelineShaderStageCreateInfo uiStages[2] = {}; - uiStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - uiStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - uiStages[0].module = uiVertModule; - uiStages[0].pName = "main"; - uiStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - uiStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - uiStages[1].module = uiFragModule; - uiStages[1].pName = "main"; - - VkPipelineColorBlendAttachmentState uiBlendAttachment = {}; - uiBlendAttachment.blendEnable = VK_TRUE; - uiBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - uiBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - uiBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; - uiBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - uiBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - uiBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; - uiBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | - VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | - VK_COLOR_COMPONENT_A_BIT; - - VkPipelineColorBlendStateCreateInfo uiCbState = {}; - uiCbState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - uiCbState.attachmentCount = 1; - uiCbState.pAttachments = &uiBlendAttachment; - - VkPipelineDepthStencilStateCreateInfo uiDepthState = {}; - uiDepthState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - uiDepthState.depthTestEnable = VK_FALSE; - uiDepthState.depthWriteEnable = VK_FALSE; - uiDepthState.depthCompareOp = VK_COMPARE_OP_ALWAYS; - uiDepthState.depthBoundsTestEnable = VK_FALSE; - uiDepthState.stencilTestEnable = VK_FALSE; - - VkGraphicsPipelineCreateInfo uiGpCI = {}; - uiGpCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - uiGpCI.stageCount = 2; - uiGpCI.pStages = uiStages; - uiGpCI.pVertexInputState = &viState; - uiGpCI.pInputAssemblyState = &iaState; - uiGpCI.pViewportState = &vpState; - uiGpCI.pRasterizationState = &rsState; - uiGpCI.pMultisampleState = &msState; - uiGpCI.pDepthStencilState = &uiDepthState; - uiGpCI.pColorBlendState = &uiCbState; - uiGpCI.layout = g_vkUiPipelineLayout; - uiGpCI.renderPass = g_vkRenderPass; - uiGpCI.subpass = 0; - - result = vkCreateGraphicsPipelines(g_vkDevice, VK_NULL_HANDLE, 1, &uiGpCI, - nullptr, &g_vkUiPipeline); - vkDestroyShaderModule(g_vkDevice, uiVertModule, nullptr); - vkDestroyShaderModule(g_vkDevice, uiFragModule, nullptr); - if (result != VK_SUCCESS || g_vkUiPipeline == VK_NULL_HANDLE) { - debugVkResult("Failed to create UI graphics pipeline", result); - return false; - } - - if (g_vkUiImageView != VK_NULL_HANDLE && g_vkUiSampler != VK_NULL_HANDLE && - g_vkUiImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - updateUiDescriptorSet(); - } - - g_vkFramebuffers.assign(g_vkSwapImageViews.size(), VK_NULL_HANDLE); - for (size_t i = 0; i < g_vkSwapImageViews.size(); ++i) { - VkImageView attachments[] = {g_vkSwapImageViews[i], g_vkDepthImageView}; - VkFramebufferCreateInfo fbCI = {}; - fbCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fbCI.renderPass = g_vkRenderPass; - fbCI.attachmentCount = 2; - fbCI.pAttachments = attachments; - fbCI.width = g_vkSwapExtent.width; - fbCI.height = g_vkSwapExtent.height; - fbCI.layers = 1; - result = vkCreateFramebuffer(g_vkDevice, &fbCI, nullptr, &g_vkFramebuffers[i]); - if (result != VK_SUCCESS) { - debugVkResult("Failed to create framebuffer", result); - return false; - } - } - - return true; -} - -// ============================================================================ -// Identity matrix helper -// ============================================================================ -static void mat4_identity(float *m) { - memset(m, 0, 16 * sizeof(float)); - m[0] = m[5] = m[10] = m[15] = 1.0f; -} - -static void mat4_multiply(float *out, const float *a, const float *b) { - float tmp[16]; - // Column-major matrix multiply (OpenGL convention): - // out = a * b, index = row + col*4. - for (int col = 0; col < 4; ++col) { - for (int row = 0; row < 4; ++row) { - float sum = 0.0f; - for (int k = 0; k < 4; ++k) { - sum += a[row + k * 4] * b[k + col * 4]; - } - tmp[row + col * 4] = sum; - } - } - memcpy(out, tmp, 16 * sizeof(float)); -} - -static bool mat4_inverse(float *out, const float *m) { - float inv[16]; - - inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + - m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - - m[13] * m[7] * m[10]; - inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + - m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + - m[12] * m[7] * m[10]; - inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + - m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - - m[12] * m[7] * m[9]; - inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + - m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - - m[12] * m[5] * m[10] + m[12] * m[6] * m[9]; - inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + - m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + - m[13] * m[3] * m[10]; - inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + - m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - - m[12] * m[3] * m[10]; - inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + - m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + - m[12] * m[3] * m[9]; - inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + - m[12] * m[1] * m[10] - m[12] * m[2] * m[9]; - inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + - m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6]; - inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + - m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + - m[12] * m[3] * m[6]; - inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + - m[12] * m[1] * m[7] - m[12] * m[3] * m[5]; - inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + - m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - - m[12] * m[1] * m[6] + m[12] * m[2] * m[5]; - inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + - m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + - m[9] * m[3] * m[6]; - inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + - m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6]; - inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + - m[4] * m[1] * m[11] - m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + - m[8] * m[3] * m[5]; - inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + - m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5]; - - const float det = - m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12]; - if (std::fabs(det) <= 1.0e-8f) { - return false; - } - - const float invDet = 1.0f / det; - for (int i = 0; i < 16; ++i) { - out[i] = inv[i] * invDet; - } - return true; -} - -static float *curMatrix() { - ensureThreadLocalMatrixStacksInitialised(); - return g_matStacks[g_curMatrixMode].stack[g_matStacks[g_curMatrixMode].top]; -} - -static void appendOverlayQuad(std::vector &verts, float x0, - float y0, float x1, float y1, uint8_t r, - uint8_t g, uint8_t b, uint8_t a) { - BootstrapVertex v0 = {x0, y0, 0.0f, 0.0f, 0.0f, r, g, b, a, 0, 0, 0, 0, 0}; - BootstrapVertex v1 = {x1, y0, 0.0f, 1.0f, 0.0f, r, g, b, a, 0, 0, 0, 0, 0}; - BootstrapVertex v2 = {x1, y1, 0.0f, 1.0f, 1.0f, r, g, b, a, 0, 0, 0, 0, 0}; - BootstrapVertex v3 = {x0, y1, 0.0f, 0.0f, 1.0f, r, g, b, a, 0, 0, 0, 0, 0}; - verts.push_back(v0); - verts.push_back(v1); - verts.push_back(v2); - verts.push_back(v2); - verts.push_back(v3); - verts.push_back(v0); -} - -static const char *const *overlayGlyph5x7Rows(char c) { - static const char *const g0[7] = {"01110", "10001", "10011", "10101", - "11001", "10001", "01110"}; - static const char *const g1[7] = {"00100", "01100", "00100", "00100", - "00100", "00100", "01110"}; - static const char *const g2[7] = {"01110", "10001", "00001", "00010", - "00100", "01000", "11111"}; - static const char *const g3[7] = {"11110", "00001", "00001", "01110", - "00001", "00001", "11110"}; - static const char *const g4[7] = {"00010", "00110", "01010", "10010", - "11111", "00010", "00010"}; - static const char *const g5[7] = {"11111", "10000", "10000", "11110", - "00001", "00001", "11110"}; - static const char *const g6[7] = {"01110", "10000", "10000", "11110", - "10001", "10001", "01110"}; - static const char *const g7[7] = {"11111", "00001", "00010", "00100", - "01000", "01000", "01000"}; - static const char *const g8[7] = {"01110", "10001", "10001", "01110", - "10001", "10001", "01110"}; - static const char *const g9[7] = {"01110", "10001", "10001", "01111", - "00001", "00001", "01110"}; - static const char *const gF[7] = {"11111", "10000", "10000", "11110", - "10000", "10000", "10000"}; - static const char *const gD[7] = {"11110", "10001", "10001", "10001", - "10001", "10001", "11110"}; - static const char *const gV[7] = {"10001", "10001", "10001", "10001", - "01010", "01010", "00100"}; - static const char *const gU[7] = {"10001", "10001", "10001", "10001", - "10001", "10001", "01110"}; - static const char *const gMinus[7] = {"00000", "00000", "00000", "11111", - "00000", "00000", "00000"}; - - switch (c) { - case '0': - return g0; - case '1': - return g1; - case '2': - return g2; - case '3': - return g3; - case '4': - return g4; - case '5': - return g5; - case '6': - return g6; - case '7': - return g7; - case '8': - return g8; - case '9': - return g9; - case 'F': - return gF; - case 'D': - return gD; - case 'V': - return gV; - case 'U': - return gU; - case '-': - return gMinus; - default: - break; - } - return nullptr; -} - -static void appendOverlayText5x7(std::vector &verts, - const char *text, float x, float y, float cellW, - float cellH, uint8_t r, uint8_t g, uint8_t b, - uint8_t a) { - if (text == nullptr) - return; - float cursorX = x; - for (const char *p = text; *p != '\0'; ++p) { - if (*p == ' ') { - cursorX += cellW * 6.0f; - continue; - } - const char *const *rows = overlayGlyph5x7Rows(*p); - if (rows != nullptr) { - for (int row = 0; row < 7; ++row) { - for (int col = 0; col < 5; ++col) { - if (rows[row][col] != '1') - continue; - const float x0 = cursorX + static_cast(col) * cellW; - const float y0 = y + static_cast(row) * cellH; - const float x1 = x0 + cellW * 0.86f; - const float y1 = y0 + cellH * 0.86f; - appendOverlayQuad(verts, x0, y0, x1, y1, r, g, b, a); - } - } - } - cursorX += cellW * 6.0f; - } -} - -static void queueCornerOverlayText() { - if (!g_vkShowCornerOverlay) - return; - - std::vector verts; - verts.reserve(1400); - - const float xStart = -0.985f; - const float cellW = 0.018f; - const float cellH = 0.030f; - - const char *glyphV[7] = {"10001", "10001", "10001", "10001", - "01010", "01010", "00100"}; - const char *glyphK[7] = {"10001", "10010", "10100", "11000", - "10100", "10010", "10001"}; - - auto emitGlyph = [&](const char *rows[7], float xOffset, float yStart) { - for (int row = 0; row < 7; ++row) { - for (int col = 0; col < 5; ++col) { - if (rows[row][col] != '1') - continue; - const float x0 = xStart + (xOffset + static_cast(col)) * cellW; - const float y0 = yStart + static_cast(row) * cellH; - const float x1 = x0 + cellW * 0.85f; - const float y1 = y0 + cellH * 0.85f; - appendOverlayQuad(verts, x0, y0, x1, y1, 255, 230, 40, 255); - } - } - }; - - auto emitBadgeAtY = [&](float yStart) { - appendOverlayQuad(verts, xStart - 0.01f, yStart - 0.01f, - xStart + cellW * 13.0f, yStart + cellH * 8.0f, 0, 0, 0, - 180); - emitGlyph(glyphV, 0.0f, yStart); - emitGlyph(glyphK, 7.0f, yStart); - }; - - emitBadgeAtY(-0.945f); - emitBadgeAtY(0.705f); - - if (g_vkShowPerfOverlay) { - const float px = xStart - 0.01f; - const float py = -0.675f; - const float pw = cellW * 20.0f; - const float ph = cellH * 10.8f; - appendOverlayQuad(verts, px, py, px + pw, py + ph, 0, 0, 0, 170); - - char fpsText[16]; - char drawText[16]; - char vertKText[16]; - char uploadKBText[16]; - - std::snprintf(fpsText, sizeof(fpsText), "%u", - static_cast(g_vkPerfFpsSmoothed + 0.5f)); - std::snprintf(drawText, sizeof(drawText), "%u", g_vkPerfDrawCount); - std::snprintf(vertKText, sizeof(vertKText), "%u", g_vkPerfVertexCount / 1000u); - std::snprintf(uploadKBText, sizeof(uploadKBText), "%u", - g_vkPerfUploadBytes / 1024u); - - const float sx = xStart + 0.005f; - const float sy = py + 0.010f; - const float sw = cellW * 0.64f; - const float sh = cellH * 0.44f; - const float dy = cellH * 2.2f; - - appendOverlayText5x7(verts, "F", sx, sy + dy * 0.0f, sw, sh, 255, 220, 60, 255); - appendOverlayText5x7(verts, fpsText, sx + sw * 8.0f, sy + dy * 0.0f, sw, sh, - 230, 230, 230, 255); - appendOverlayText5x7(verts, "D", sx, sy + dy * 1.0f, sw, sh, 255, 220, 60, 255); - appendOverlayText5x7(verts, drawText, sx + sw * 8.0f, sy + dy * 1.0f, sw, sh, - 230, 230, 230, 255); - appendOverlayText5x7(verts, "V", sx, sy + dy * 2.0f, sw, sh, 255, 220, 60, 255); - appendOverlayText5x7(verts, vertKText, sx + sw * 8.0f, sy + dy * 2.0f, sw, sh, - 230, 230, 230, 255); - appendOverlayText5x7(verts, "U", sx, sy + dy * 3.0f, sw, sh, 255, 220, 60, 255); - appendOverlayText5x7(verts, uploadKBText, sx + sw * 8.0f, sy + dy * 3.0f, sw, sh, - 230, 230, 230, 255); - } - - if (verts.empty()) - return; - - const size_t oldSize = g_vkFrameVertexData.size(); - const size_t addBytes = verts.size() * sizeof(BootstrapVertex); - g_vkFrameVertexData.resize(oldSize + addBytes); - std::memcpy(g_vkFrameVertexData.data() + oldSize, verts.data(), addBytes); - - VulkanQueuedDraw draw = {}; - draw.firstVertex = - static_cast(oldSize / kVertexStridePF3TF2CB4NB4XW1); - draw.vertexCount = static_cast(verts.size()); - mat4_identity(draw.mvp); - draw.depthTestEnable = false; - draw.depthWriteEnable = false; - draw.depthCompareOp = VK_COMPARE_OP_ALWAYS; - draw.blendEnable = false; - draw.srcBlendFactor = VK_BLEND_FACTOR_ONE; - draw.dstBlendFactor = VK_BLEND_FACTOR_ZERO; - draw.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - draw.cullEnable = false; - draw.cullClockwise = true; - draw.blendConstants[0] = 1.0f; - draw.blendConstants[1] = 1.0f; - draw.blendConstants[2] = 1.0f; - draw.blendConstants[3] = 1.0f; - g_vkQueuedDraws.push_back(draw); -} - -static void appendUiCompositeFullscreenQuad(uint32_t &firstVertexOut, - uint32_t &vertexCountOut) { - firstVertexOut = 0; - vertexCountOut = 0; - if (!g_vkUiImageReady) - return; - - const BootstrapVertex verts[6] = { - {-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 255, 255, 255, 255, 0, 0, 0, 0, 0}, - {+1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 255, 255, 255, 255, 0, 0, 0, 0, 0}, - {+1.0f, +1.0f, 0.0f, 1.0f, 0.0f, 255, 255, 255, 255, 0, 0, 0, 0, 0}, - {+1.0f, +1.0f, 0.0f, 1.0f, 0.0f, 255, 255, 255, 255, 0, 0, 0, 0, 0}, - {-1.0f, +1.0f, 0.0f, 0.0f, 0.0f, 255, 255, 255, 255, 0, 0, 0, 0, 0}, - {-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 255, 255, 255, 255, 0, 0, 0, 0, 0}, - }; - - const size_t oldSize = g_vkFrameVertexData.size(); - const size_t addBytes = sizeof(verts); - g_vkFrameVertexData.resize(oldSize + addBytes); - std::memcpy(g_vkFrameVertexData.data() + oldSize, verts, addBytes); - - firstVertexOut = - static_cast(oldSize / kVertexStridePF3TF2CB4NB4XW1); - vertexCountOut = 6; -} - -// ============================================================================ -// C4JRender — Matrix stack -// ============================================================================ - -void C4JRender::MatrixMode(int type) { - ensureThreadLocalMatrixStacksInitialised(); - if (type >= 0 && type < NUM_MATRIX_MODES) - g_curMatrixMode = type; -} - -void C4JRender::MatrixSetIdentity() { - mat4_identity(curMatrix()); - g_matrixDirty = true; -} - -void C4JRender::MatrixTranslate(float x, float y, float z) { - float t[16]; - mat4_identity(t); - t[12] = x; - t[13] = y; - t[14] = z; - mat4_multiply(curMatrix(), curMatrix(), t); - g_matrixDirty = true; -} - -void C4JRender::MatrixRotate(float angle, float x, float y, float z) { - float c = cosf(angle), s = sinf(angle); - float len = sqrtf(x * x + y * y + z * z); - if (len < 1e-6f) - return; - x /= len; - y /= len; - z /= len; - float t = 1.0f - c; - - float r[16]; - mat4_identity(r); - r[0] = t * x * x + c; - r[4] = t * x * y - s * z; - r[8] = t * x * z + s * y; - r[1] = t * x * y + s * z; - r[5] = t * y * y + c; - r[9] = t * y * z - s * x; - r[2] = t * x * z - s * y; - r[6] = t * y * z + s * x; - r[10] = t * z * z + c; - - mat4_multiply(curMatrix(), curMatrix(), r); - g_matrixDirty = true; -} - -void C4JRender::MatrixScale(float x, float y, float z) { - float s[16]; - mat4_identity(s); - s[0] = x; - s[5] = y; - s[10] = z; - mat4_multiply(curMatrix(), curMatrix(), s); - g_matrixDirty = true; -} - -void C4JRender::MatrixPerspective(float fovy, float aspect, float zNear, - float zFar) { - // gluPerspective-style input is degrees. - const float fovyRadians = fovy * (3.14159265358979323846f / 180.0f); - float f = 1.0f / tanf(fovyRadians * 0.5f); - float p[16]; - memset(p, 0, sizeof(p)); - p[0] = f / aspect; - p[5] = f; - p[10] = (zFar + zNear) / (zNear - zFar); - p[11] = -1.0f; - p[14] = (2.0f * zFar * zNear) / (zNear - zFar); - mat4_multiply(curMatrix(), curMatrix(), p); - g_matrixDirty = true; -} - -void C4JRender::MatrixOrthogonal(float left, float right, float bottom, - float top, float zNear, float zFar) { - float o[16]; - memset(o, 0, sizeof(o)); - o[0] = 2.0f / (right - left); - o[5] = 2.0f / (top - bottom); - o[10] = -2.0f / (zFar - zNear); - o[12] = -(right + left) / (right - left); - o[13] = -(top + bottom) / (top - bottom); - o[14] = -(zFar + zNear) / (zFar - zNear); - o[15] = 1.0f; - mat4_multiply(curMatrix(), curMatrix(), o); - g_matrixDirty = true; -} - -void C4JRender::MatrixPop() { - auto &s = g_matStacks[g_curMatrixMode]; - if (s.top > 0) - s.top--; - g_matrixDirty = true; -} - -void C4JRender::MatrixPush() { - auto &s = g_matStacks[g_curMatrixMode]; - if (s.top < MATRIX_STACK_DEPTH - 1) { - memcpy(s.stack[s.top + 1], s.stack[s.top], 16 * sizeof(float)); - s.top++; - } - g_matrixDirty = true; -} - -void C4JRender::MatrixMult(float *mat) { - mat4_multiply(curMatrix(), curMatrix(), mat); - g_matrixDirty = true; -} - -const float *C4JRender::MatrixGet(int type) { - ensureThreadLocalMatrixStacksInitialised(); - if (type >= 0 && type < NUM_MATRIX_MODES) - return g_matStacks[type].stack[g_matStacks[type].top]; - return g_matStacks[0].stack[g_matStacks[0].top]; -} - -void C4JRender::Set_matrixDirty() { g_matrixDirty = true; } - -// ============================================================================ -// C4JRender - Core (Vulkan init and present) -// ============================================================================ - -void C4JRender::Initialise(HWND hWnd, int width, int height) { - g_vkWindow = hWnd; - destroyVulkanRuntime(); - - if (width <= 0 || height <= 0) { - int clientW = 0; - int clientH = 0; - if (getWindowClientSize(hWnd, clientW, clientH)) { - width = clientW; - height = clientH; - } - } - if (width <= 0 || height <= 0) { - debugVk("C4JRender_Vulkan: Skipping init for zero-sized window.\n"); - return; - } - - // Init matrix stacks - ensureThreadLocalMatrixStacksInitialised(); - for (int i = 0; i < NUM_MATRIX_MODES; i++) { - g_matStacks[i].top = 0; - mat4_identity(g_matStacks[i].stack[0]); - } - resetThreadLocalRenderState(); - - // ---- VkInstance ---- - VkApplicationInfo appInfo = {}; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "MinecraftConsoles"; - appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.pEngineName = "4JRender_Vulkan"; - appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.apiVersion = VK_API_VERSION_1_2; - - const char *extensions[] = { - VK_KHR_SURFACE_EXTENSION_NAME, - VK_KHR_WIN32_SURFACE_EXTENSION_NAME, - }; - - VkInstanceCreateInfo ci = {}; - ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - ci.pApplicationInfo = &appInfo; - ci.enabledExtensionCount = 2; - ci.ppEnabledExtensionNames = extensions; - -#ifdef _DEBUG - const char *layers[] = {"VK_LAYER_KHRONOS_validation"}; - if (hasValidationLayer(layers[0])) { - ci.enabledLayerCount = 1; - ci.ppEnabledLayerNames = layers; - } else { - debugVk("C4JRender_Vulkan: Validation layer not available; continuing " - "without it.\n"); - } -#endif - - VkResult result = vkCreateInstance(&ci, nullptr, &g_vkInstance); - if (result != VK_SUCCESS) { - debugVkResult("Failed to create VkInstance", result); - return; - } - - // ---- Surface ---- - VkWin32SurfaceCreateInfoKHR surfCI = {}; - surfCI.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; - surfCI.hinstance = GetModuleHandle(NULL); - surfCI.hwnd = hWnd; - result = vkCreateWin32SurfaceKHR(g_vkInstance, &surfCI, nullptr, &g_vkSurface); - if (result != VK_SUCCESS) { - debugVkResult("Failed to create Win32 surface", result); - return; - } - - // ---- Physical device ---- - uint32_t devCount = 0; - result = vkEnumeratePhysicalDevices(g_vkInstance, &devCount, nullptr); - if (result != VK_SUCCESS || devCount == 0) { - debugVk("C4JRender_Vulkan: No Vulkan physical devices found.\n"); - return; - } - - std::vector devices(devCount); - result = vkEnumeratePhysicalDevices(g_vkInstance, &devCount, devices.data()); - if (result != VK_SUCCESS) { - debugVkResult("Failed to enumerate Vulkan physical devices", result); - return; - } - - bool foundDeviceAndQueue = false; - for (uint32_t d = 0; d < devCount && !foundDeviceAndQueue; ++d) { - VkPhysicalDevice candidate = devices[d]; - uint32_t qfCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties(candidate, &qfCount, nullptr); - if (qfCount == 0) - continue; - - std::vector qfProps(qfCount); - vkGetPhysicalDeviceQueueFamilyProperties(candidate, &qfCount, - qfProps.data()); - for (uint32_t i = 0; i < qfCount; i++) { - VkBool32 presentSupport = VK_FALSE; - result = vkGetPhysicalDeviceSurfaceSupportKHR(candidate, i, g_vkSurface, - &presentSupport); - if (result != VK_SUCCESS) - continue; - if ((qfProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && presentSupport) { - g_vkPhysicalDevice = candidate; - g_vkGraphicsFamily = i; - foundDeviceAndQueue = true; - break; - } - } - } - if (!foundDeviceAndQueue || g_vkPhysicalDevice == VK_NULL_HANDLE) { - debugVk("C4JRender_Vulkan: Failed to find graphics+present queue family.\n"); - return; - } - - // ---- Logical device ---- - float queuePriority = 1.0f; - VkDeviceQueueCreateInfo qCI = {}; - qCI.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - qCI.queueFamilyIndex = g_vkGraphicsFamily; - qCI.queueCount = 1; - qCI.pQueuePriorities = &queuePriority; - - const char *devExts[] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; - VkDeviceCreateInfo devCI = {}; - devCI.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - devCI.queueCreateInfoCount = 1; - devCI.pQueueCreateInfos = &qCI; - devCI.enabledExtensionCount = 1; - devCI.ppEnabledExtensionNames = devExts; - - result = vkCreateDevice(g_vkPhysicalDevice, &devCI, nullptr, &g_vkDevice); - if (result != VK_SUCCESS) { - debugVkResult("Failed to create VkDevice", result); - return; - } - vkGetDeviceQueue(g_vkDevice, g_vkGraphicsFamily, 0, &g_vkGraphicsQueue); - if (g_vkGraphicsQueue == VK_NULL_HANDLE) { - debugVk("C4JRender_Vulkan: Failed to get graphics queue.\n"); - return; - } - - // ---- Swapchain ---- - VkSurfaceCapabilitiesKHR caps; - result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_vkPhysicalDevice, - g_vkSurface, &caps); - if (result != VK_SUCCESS) { - debugVkResult("Failed to query surface capabilities", result); - return; - } - - uint32_t formatCount = 0; - result = - vkGetPhysicalDeviceSurfaceFormatsKHR(g_vkPhysicalDevice, g_vkSurface, - &formatCount, nullptr); - if (result != VK_SUCCESS || formatCount == 0) { - debugVk("C4JRender_Vulkan: No swapchain surface formats available.\n"); - return; - } - - std::vector formats(formatCount); - result = vkGetPhysicalDeviceSurfaceFormatsKHR(g_vkPhysicalDevice, g_vkSurface, - &formatCount, formats.data()); - if (result != VK_SUCCESS) { - debugVkResult("Failed to query surface formats", result); - return; - } - - VkSurfaceFormatKHR chosenFormat = formats[0]; - for (const auto &f : formats) { - if (f.format == VK_FORMAT_B8G8R8A8_UNORM && - f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - chosenFormat = f; - break; - } - } - g_vkSwapFormat = chosenFormat.format; - - g_vkSwapExtent.width = (uint32_t)width; - g_vkSwapExtent.height = (uint32_t)height; - if (caps.currentExtent.width != UINT32_MAX) { - g_vkSwapExtent = caps.currentExtent; - } - - uint32_t imageCount = caps.minImageCount + 1; - if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) - imageCount = caps.maxImageCount; - - VkSwapchainCreateInfoKHR scCI = {}; - scCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - scCI.surface = g_vkSurface; - scCI.minImageCount = imageCount; - scCI.imageFormat = chosenFormat.format; - scCI.imageColorSpace = chosenFormat.colorSpace; - scCI.imageExtent = g_vkSwapExtent; - scCI.imageArrayLayers = 1; - if (!(caps.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) { - debugVk("C4JRender_Vulkan: Surface does not support COLOR_ATTACHMENT usage.\n"); - return; - } - scCI.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - scCI.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - scCI.preTransform = caps.currentTransform; - if (caps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { - scCI.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - } - if (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) { - scCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - } else if (caps.supportedCompositeAlpha & - VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) { - scCI.compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR; - } else if (caps.supportedCompositeAlpha & - VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) { - scCI.compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR; - } else { - scCI.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; - } - scCI.presentMode = VK_PRESENT_MODE_FIFO_KHR; - scCI.clipped = VK_TRUE; - - result = vkCreateSwapchainKHR(g_vkDevice, &scCI, nullptr, &g_vkSwapchain); - if (result != VK_SUCCESS) { - debugVkResult("Failed to create swapchain", result); - return; - } - - uint32_t swapImgCount = 0; - result = - vkGetSwapchainImagesKHR(g_vkDevice, g_vkSwapchain, &swapImgCount, nullptr); - if (result != VK_SUCCESS || swapImgCount == 0) { - debugVk("C4JRender_Vulkan: Failed to query swapchain image count.\n"); - return; - } - g_vkSwapImages.resize(swapImgCount); - result = vkGetSwapchainImagesKHR(g_vkDevice, g_vkSwapchain, &swapImgCount, - g_vkSwapImages.data()); - if (result != VK_SUCCESS) { - debugVkResult("Failed to get swapchain images", result); - return; - } - g_vkSwapImageLayouts.assign(swapImgCount, VK_IMAGE_LAYOUT_UNDEFINED); - - if (!createTriangleRenderResources()) { - debugVk("C4JRender_Vulkan: Failed to create triangle render resources.\n"); - return; - } - - // ---- Command pool + buffer ---- - VkCommandPoolCreateInfo cpCI = {}; - cpCI.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cpCI.queueFamilyIndex = g_vkGraphicsFamily; - cpCI.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - result = vkCreateCommandPool(g_vkDevice, &cpCI, nullptr, &g_vkCommandPool); - if (result != VK_SUCCESS || g_vkCommandPool == VK_NULL_HANDLE) { - debugVkResult("Failed to create command pool", result); - return; - } - - VkCommandBufferAllocateInfo cbAI = {}; - cbAI.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - cbAI.commandPool = g_vkCommandPool; - cbAI.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - cbAI.commandBufferCount = 1; - result = vkAllocateCommandBuffers(g_vkDevice, &cbAI, &g_vkCommandBuffer); - if (result != VK_SUCCESS || g_vkCommandBuffer == VK_NULL_HANDLE) { - debugVkResult("Failed to allocate command buffer", result); - return; - } - - // ---- Sync objects ---- - VkFenceCreateInfo fCI = {}; - fCI.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fCI.flags = VK_FENCE_CREATE_SIGNALED_BIT; - result = vkCreateFence(g_vkDevice, &fCI, nullptr, &g_vkFence); - if (result != VK_SUCCESS || g_vkFence == VK_NULL_HANDLE) { - debugVkResult("Failed to create fence", result); - return; - } - - VkSemaphoreCreateInfo sCI = {}; - sCI.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - result = vkCreateSemaphore(g_vkDevice, &sCI, nullptr, &g_vkImageAvailable); - if (result != VK_SUCCESS || g_vkImageAvailable == VK_NULL_HANDLE) { - debugVkResult("Failed to create image-available semaphore", result); - return; - } - result = vkCreateSemaphore(g_vkDevice, &sCI, nullptr, &g_vkRenderFinished); - if (result != VK_SUCCESS || g_vkRenderFinished == VK_NULL_HANDLE) { - debugVkResult("Failed to create render-finished semaphore", result); - return; - } - - if (!ensureWhiteTexture()) { - debugVk("C4JRender_Vulkan: Failed to create fallback white texture.\n"); - return; - } - - g_vkInitialized = true; - g_isWidescreen = (height > 0) ? (((float)width / (float)height) > 1.5f) : true; - - debugVk("C4JRender_Vulkan: Initialised OK!\n"); -} - -void C4JRender::InitialiseContext() {} -void C4JRender::Tick() {} -void C4JRender::UpdateGamma(unsigned short) {} - -void C4JRender::StartFrame() { - g_vkFrameVertexData.clear(); - g_vkQueuedDraws.clear(); - if (g_vkFrameVertexData.capacity() < g_vkFrameVertexReserveBytes) { - g_vkFrameVertexData.reserve(g_vkFrameVertexReserveBytes); - } - if (g_vkQueuedDraws.capacity() < g_vkFrameDrawReserveCount) { - g_vkQueuedDraws.reserve(g_vkFrameDrawReserveCount); - } - - if (!g_vkInitialized) - return; - - VkResult result = vkWaitForFences(g_vkDevice, 1, &g_vkFence, VK_TRUE, - UINT64_MAX); - if (result != VK_SUCCESS) { - debugVkResult("vkWaitForFences failed", result); - g_vkInitialized = false; - return; - } - - processPendingTextureUploads(); -} - -static bool updateUiDescriptorSet() { - if (g_vkDevice == VK_NULL_HANDLE || g_vkUiDescriptorSet == VK_NULL_HANDLE) - return false; - if (g_vkUiImageView == VK_NULL_HANDLE || g_vkUiSampler == VK_NULL_HANDLE) - return false; - - VkDescriptorImageInfo imageInfo = {}; - imageInfo.sampler = g_vkUiSampler; - imageInfo.imageView = g_vkUiImageView; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet write = {}; - write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write.dstSet = g_vkUiDescriptorSet; - write.dstBinding = 0; - write.dstArrayElement = 0; - write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - write.descriptorCount = 1; - write.pImageInfo = &imageInfo; - vkUpdateDescriptorSets(g_vkDevice, 1, &write, 0, nullptr); - return true; -} - -static bool recordPendingUiUpload(VkCommandBuffer cmd) { - if (!g_vkUiUpload.pending) - return true; - if (g_vkDevice == VK_NULL_HANDLE) - return false; - - const size_t dataBytes = g_vkUiUpload.pixelsBGRA.size(); - if (dataBytes == 0 || g_vkUiUpload.width == 0 || g_vkUiUpload.height == 0) - return true; - - if (!createOrResizeUiImageResources(g_vkUiUpload.width, g_vkUiUpload.height)) - return false; - if (!ensureUiStagingBuffer(dataBytes)) - return false; - if (g_vkUiStagingMapped == nullptr) - return false; - - VkResult result = VK_SUCCESS; - std::memcpy(g_vkUiStagingMapped, g_vkUiUpload.pixelsBGRA.data(), dataBytes); - if (!g_vkUiStagingHostCoherent) { - VkMappedMemoryRange range = {}; - range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range.memory = g_vkUiStagingMemory; - range.offset = 0; - range.size = VK_WHOLE_SIZE; - result = vkFlushMappedMemoryRanges(g_vkDevice, 1, &range); - if (result != VK_SUCCESS) { - debugVkResult("Failed to flush UI staging memory", result); - return false; - } - } - - VkImageMemoryBarrier toTransfer = {}; - toTransfer.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - toTransfer.oldLayout = g_vkUiImageLayout; - toTransfer.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - toTransfer.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - toTransfer.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - toTransfer.image = g_vkUiImage; - toTransfer.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - toTransfer.subresourceRange.baseMipLevel = 0; - toTransfer.subresourceRange.levelCount = 1; - toTransfer.subresourceRange.baseArrayLayer = 0; - toTransfer.subresourceRange.layerCount = 1; - - VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - if (g_vkUiImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - srcStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - toTransfer.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - } else if (g_vkUiImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { - srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - toTransfer.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - } else { - toTransfer.srcAccessMask = 0; - } - toTransfer.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - - vkCmdPipelineBarrier(cmd, srcStage, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, - nullptr, 0, nullptr, 1, &toTransfer); - - VkBufferImageCopy copyRegion = {}; - copyRegion.bufferOffset = 0; - copyRegion.bufferRowLength = 0; - copyRegion.bufferImageHeight = 0; - copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.imageSubresource.mipLevel = 0; - copyRegion.imageSubresource.baseArrayLayer = 0; - copyRegion.imageSubresource.layerCount = 1; - copyRegion.imageOffset = {0, 0, 0}; - copyRegion.imageExtent = {g_vkUiUpload.width, g_vkUiUpload.height, 1}; - vkCmdCopyBufferToImage(cmd, g_vkUiStagingBuffer, g_vkUiImage, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); - - VkImageMemoryBarrier toRead = {}; - toRead.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - toRead.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - toRead.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - toRead.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - toRead.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - toRead.image = g_vkUiImage; - toRead.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - toRead.subresourceRange.baseMipLevel = 0; - toRead.subresourceRange.levelCount = 1; - toRead.subresourceRange.baseArrayLayer = 0; - toRead.subresourceRange.layerCount = 1; - toRead.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - toRead.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &toRead); - - g_vkUiImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - g_vkUiImageReady = true; - g_vkUiUpload.pending = false; - - updateUiDescriptorSet(); - return true; -} - -void C4JRender::Present() { - if (!g_vkInitialized) - return; - if (g_vkSwapImages.empty() || g_vkSwapImageLayouts.empty() || - g_vkFramebuffers.empty() || g_vkCommandBuffer == VK_NULL_HANDLE || - g_vkRenderPass == VK_NULL_HANDLE || g_vkTrianglePipeline == VK_NULL_HANDLE) - return; - - uint32_t imageIndex = 0; - bool needRecreateSwapchain = false; - VkResult result = - vkAcquireNextImageKHR(g_vkDevice, g_vkSwapchain, UINT64_MAX, - g_vkImageAvailable, VK_NULL_HANDLE, &imageIndex); - if (result == VK_ERROR_OUT_OF_DATE_KHR) { - needRecreateSwapchain = true; - } else if (result == VK_SUBOPTIMAL_KHR) { - needRecreateSwapchain = true; - } else if (result != VK_SUCCESS) { - debugVkResult("vkAcquireNextImageKHR failed", result); - return; - } - if (needRecreateSwapchain) { - if (g_vkWindow != NULL) { - int width = 0; - int height = 0; - if (getWindowClientSize(g_vkWindow, width, height)) { - Initialise(g_vkWindow, width, height); - } - } - return; - } - if (imageIndex >= g_vkSwapImages.size() || - imageIndex >= g_vkSwapImageLayouts.size() || - imageIndex >= g_vkFramebuffers.size()) { - debugVk("C4JRender_Vulkan: swapchain image index out of range.\n"); - return; - } - - uint64_t frameVertexCount = 0; - for (const VulkanQueuedDraw &draw : g_vkQueuedDraws) { - frameVertexCount += static_cast(draw.vertexCount); - } - g_vkPerfDrawCount = static_cast(g_vkQueuedDraws.size()); - g_vkPerfVertexCount = - (frameVertexCount > 0xffffffffull) ? 0xffffffffu - : static_cast(frameVertexCount); - g_vkPerfUploadBytes = (g_vkFrameVertexData.size() > 0xffffffffull) - ? 0xffffffffu - : static_cast(g_vkFrameVertexData.size()); - - if (g_vkPerfFreq.QuadPart == 0) { - QueryPerformanceFrequency(&g_vkPerfFreq); - } - LARGE_INTEGER nowCounter = {}; - QueryPerformanceCounter(&nowCounter); - if (g_vkPerfLastPresent.QuadPart != 0 && g_vkPerfFreq.QuadPart > 0) { - const double dtSeconds = - static_cast(nowCounter.QuadPart - g_vkPerfLastPresent.QuadPart) / - static_cast(g_vkPerfFreq.QuadPart); - if (dtSeconds > 0.000001) { - const float instFps = static_cast(1.0 / dtSeconds); - if (g_vkPerfFpsSmoothed <= 0.0f) { - g_vkPerfFpsSmoothed = instFps; - } else { - g_vkPerfFpsSmoothed = - g_vkPerfFpsSmoothed * 0.9f + instFps * 0.1f; - } - } - } - g_vkPerfLastPresent = nowCounter; - - queueCornerOverlayText(); - uint32_t uiQuadFirstVertex = 0; - uint32_t uiQuadVertexCount = 0; - if (g_vkUiImageReady || g_vkUiUpload.pending) { - appendUiCompositeFullscreenQuad(uiQuadFirstVertex, uiQuadVertexCount); - } - - if (!g_vkFrameVertexData.empty()) { - if (!ensureDynamicVertexBuffer(g_vkFrameVertexData.size())) { - debugVk("C4JRender_Vulkan: Failed to ensure dynamic vertex buffer.\n"); - return; - } - if (g_vkDynamicVertexMapped == nullptr) { - debugVk("C4JRender_Vulkan: Dynamic vertex buffer not mapped.\n"); - return; - } - std::memcpy(g_vkDynamicVertexMapped, g_vkFrameVertexData.data(), - g_vkFrameVertexData.size()); - if (!g_vkDynamicVertexHostCoherent) { - VkMappedMemoryRange range = {}; - range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range.memory = g_vkDynamicVertexMemory; - range.offset = 0; - range.size = VK_WHOLE_SIZE; - result = vkFlushMappedMemoryRanges(g_vkDevice, 1, &range); - if (result != VK_SUCCESS) { - debugVkResult("vkFlushMappedMemoryRanges failed", result); - return; - } - } - } - - result = vkResetCommandBuffer(g_vkCommandBuffer, 0); - if (result != VK_SUCCESS) { - debugVkResult("vkResetCommandBuffer failed", result); - return; - } - - VkCommandBufferBeginInfo beginInfo = {}; - beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - result = vkBeginCommandBuffer(g_vkCommandBuffer, &beginInfo); - if (result != VK_SUCCESS) { - debugVkResult("vkBeginCommandBuffer failed", result); - return; - } - - if (!recordPendingUiUpload(g_vkCommandBuffer)) { - debugVk("C4JRender_Vulkan: Failed to record pending UI upload.\n"); - } - - VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - if (g_vkSwapImageLayouts[imageIndex] == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) - srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - - VkImageMemoryBarrier barrier = {}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.oldLayout = g_vkSwapImageLayouts[imageIndex]; - barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = g_vkSwapImages[imageIndex]; - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = 1; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - barrier.srcAccessMask = 0; - barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - vkCmdPipelineBarrier(g_vkCommandBuffer, srcStageMask, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, - nullptr, 0, nullptr, 1, &barrier); - - VkClearValue clearValues[2] = {}; - clearValues[0].color.float32[0] = g_clearColour[0]; - clearValues[0].color.float32[1] = g_clearColour[1]; - clearValues[0].color.float32[2] = g_clearColour[2]; - clearValues[0].color.float32[3] = g_clearColour[3]; - clearValues[1].depthStencil.depth = 1.0f; - clearValues[1].depthStencil.stencil = 0; - - VkRenderPassBeginInfo rpBegin = {}; - rpBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - rpBegin.renderPass = g_vkRenderPass; - rpBegin.framebuffer = g_vkFramebuffers[imageIndex]; - rpBegin.renderArea.offset = {0, 0}; - rpBegin.renderArea.extent = g_vkSwapExtent; - rpBegin.clearValueCount = 2; - rpBegin.pClearValues = clearValues; - vkCmdBeginRenderPass(g_vkCommandBuffer, &rpBegin, VK_SUBPASS_CONTENTS_INLINE); - - if (!g_vkQueuedDraws.empty()) { - VkBuffer vertexBuffers[] = {g_vkDynamicVertexBuffer}; - VkDeviceSize offsets[] = {0}; - vkCmdBindVertexBuffers(g_vkCommandBuffer, 0, 1, vertexBuffers, offsets); - - VkPipeline boundPipeline = VK_NULL_HANDLE; - VkDescriptorSet boundDescriptorSet = VK_NULL_HANDLE; - float lastBlendConstants[4] = {-1.0f, -1.0f, -1.0f, -1.0f}; - for (const VulkanQueuedDraw &draw : g_vkQueuedDraws) { - VkPipeline pipeline = getOrCreateTrianglePipeline( - draw.depthTestEnable, draw.depthWriteEnable, draw.depthCompareOp, - draw.blendEnable, draw.srcBlendFactor, draw.dstBlendFactor, - draw.colorWriteMask, draw.cullEnable, draw.cullClockwise); - if (pipeline == VK_NULL_HANDLE) - continue; - if (pipeline != boundPipeline) { - vkCmdBindPipeline(g_vkCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline); - boundPipeline = pipeline; - } - if (std::memcmp(lastBlendConstants, draw.blendConstants, - sizeof(lastBlendConstants)) != 0) { - vkCmdSetBlendConstants(g_vkCommandBuffer, draw.blendConstants); - std::memcpy(lastBlendConstants, draw.blendConstants, - sizeof(lastBlendConstants)); - } - VkDescriptorSet descriptorSet = draw.descriptorSet; - if (descriptorSet == VK_NULL_HANDLE) { - descriptorSet = resolveTextureDescriptorSet(-1); - } - if (descriptorSet == VK_NULL_HANDLE) { - continue; - } - if (descriptorSet != boundDescriptorSet) { - vkCmdBindDescriptorSets(g_vkCommandBuffer, - VK_PIPELINE_BIND_POINT_GRAPHICS, - g_vkPipelineLayout, 0, 1, &descriptorSet, 0, - nullptr); - boundDescriptorSet = descriptorSet; - } - - TrianglePushConstants push = {}; - std::memcpy(push.mvp, draw.mvp, sizeof(push.mvp)); - push.alphaState[0] = draw.alphaTestEnable ? 1.0f : 0.0f; - push.alphaState[1] = draw.alphaRef; - push.alphaState[2] = static_cast(draw.alphaFunc); - push.alphaState[3] = 0.0f; - vkCmdPushConstants(g_vkCommandBuffer, g_vkPipelineLayout, - VK_SHADER_STAGE_VERTEX_BIT | - VK_SHADER_STAGE_FRAGMENT_BIT, - 0, sizeof(push), &push); - vkCmdDraw(g_vkCommandBuffer, draw.vertexCount, 1, draw.firstVertex, 0); - } - } - - if (uiQuadVertexCount > 0 && g_vkUiImageReady && - g_vkUiPipeline != VK_NULL_HANDLE && - g_vkUiPipelineLayout != VK_NULL_HANDLE && - g_vkUiDescriptorSet != VK_NULL_HANDLE) { - VkBuffer vertexBuffers[] = {g_vkDynamicVertexBuffer}; - VkDeviceSize offsets[] = {0}; - float identity[16]; - mat4_identity(identity); - - vkCmdBindPipeline(g_vkCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - g_vkUiPipeline); - vkCmdBindVertexBuffers(g_vkCommandBuffer, 0, 1, vertexBuffers, offsets); - vkCmdBindDescriptorSets(g_vkCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - g_vkUiPipelineLayout, 0, 1, &g_vkUiDescriptorSet, 0, - nullptr); - vkCmdPushConstants(g_vkCommandBuffer, g_vkUiPipelineLayout, - VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(identity), - identity); - vkCmdDraw(g_vkCommandBuffer, uiQuadVertexCount, 1, uiQuadFirstVertex, 0); - } - vkCmdEndRenderPass(g_vkCommandBuffer); - - result = vkEndCommandBuffer(g_vkCommandBuffer); - if (result != VK_SUCCESS) { - debugVkResult("vkEndCommandBuffer failed", result); - return; - } - - VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkSubmitInfo submitInfo = {}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = &g_vkImageAvailable; - submitInfo.pWaitDstStageMask = &waitStage; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &g_vkCommandBuffer; - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = &g_vkRenderFinished; - - result = vkResetFences(g_vkDevice, 1, &g_vkFence); - if (result != VK_SUCCESS) { - debugVkResult("vkResetFences failed", result); - g_vkInitialized = false; - return; - } - - result = vkQueueSubmit(g_vkGraphicsQueue, 1, &submitInfo, g_vkFence); - if (result != VK_SUCCESS) { - debugVkResult("vkQueueSubmit failed", result); - g_vkInitialized = false; - return; - } - - VkPresentInfoKHR presentInfo = {}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - presentInfo.waitSemaphoreCount = 1; - presentInfo.pWaitSemaphores = &g_vkRenderFinished; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = &g_vkSwapchain; - presentInfo.pImageIndices = &imageIndex; - result = vkQueuePresentKHR(g_vkGraphicsQueue, &presentInfo); - if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR && result != VK_ERROR_OUT_OF_DATE_KHR) { - debugVkResult("vkQueuePresentKHR failed", result); - return; - } - g_vkSwapImageLayouts[imageIndex] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - if (g_vkFrameVertexData.size() > g_vkFrameVertexReserveBytes) { - g_vkFrameVertexReserveBytes = g_vkFrameVertexData.size(); - } - if (g_vkQueuedDraws.size() > g_vkFrameDrawReserveCount) { - g_vkFrameDrawReserveCount = g_vkQueuedDraws.size(); - } - - if (result == VK_SUBOPTIMAL_KHR || result == VK_ERROR_OUT_OF_DATE_KHR) { - if (g_vkWindow != NULL) { - int width = 0; - int height = 0; - if (getWindowClientSize(g_vkWindow, width, height)) { - Initialise(g_vkWindow, width, height); - } - } - } -} -void C4JRender::DoScreenGrabOnNextPresent() {} -void C4JRender::Clear(int, C4JRect *) {} -void C4JRender::SetClearColour(const float c[4]) { - g_clearColour[0] = c[0]; - g_clearColour[1] = c[1]; - g_clearColour[2] = c[2]; - g_clearColour[3] = c[3]; -} -bool C4JRender::IsWidescreen() { return g_isWidescreen; } -bool C4JRender::IsHiDef() { return true; } -void C4JRender::CaptureThumbnail(ImageFileBuffer *) {} -void C4JRender::CaptureScreen(ImageFileBuffer *, XSOCIAL_PREVIEWIMAGE *) {} -void C4JRender::BeginConditionalSurvey(int) {} -void C4JRender::EndConditionalSurvey() {} -void C4JRender::BeginConditionalRendering(int) {} -void C4JRender::EndConditionalRendering() {} - -// ============================================================================ -// Draw calls -// ============================================================================ -static inline void unpack565ToRGBA(uint16_t packed, uint8_t &r, uint8_t &g, - uint8_t &b, uint8_t &a) { - const uint8_t r5 = static_cast((packed >> 11) & 0x1f); - const uint8_t g6 = static_cast((packed >> 5) & 0x3f); - const uint8_t b5 = static_cast(packed & 0x1f); - r = static_cast((r5 * 255) / 31); - g = static_cast((g6 * 255) / 63); - b = static_cast((b5 * 255) / 31); - a = 255; -} - -static inline uint8_t modulate8(uint8_t value, float mul) { - int out = static_cast(static_cast(value) * mul + 0.5f); - if (out < 0) - out = 0; - if (out > 255) - out = 255; - return static_cast(out); -} - -static inline float decodeLegacyNoMipmapU(float u) { - // old tesselator stores "no mip" as u+1.0f. - if (u > 1.0f && u < 2.0f) { - return u - 1.0f; - } - return u; -} - -static inline bool vkColourMulIsIdentity() { - return (std::fabs(g_vkStateColour[0] - 1.0f) <= 0.0001f) && - (std::fabs(g_vkStateColour[1] - 1.0f) <= 0.0001f) && - (std::fabs(g_vkStateColour[2] - 1.0f) <= 0.0001f) && - (std::fabs(g_vkStateColour[3] - 1.0f) <= 0.0001f); -} - -static uint32_t expandVertexStreamToBootstrap( - std::vector &out, C4JRender::ePrimitiveType primitiveType, - int count, C4JRender::eVertexType vType, const uint8_t *srcBytes, - bool applyColourMul, float colourMulR, float colourMulG, float colourMulB, - float colourMulA) { - const bool isStandardVertex = - (vType == C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1 || - vType == C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_TEXGEN || - vType == C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_LIT); - const bool isCompressedVertex = (vType == C4JRender::VERTEX_TYPE_COMPRESSED); - if (!isStandardVertex && !isCompressedVertex) - return 0; - - if (primitiveType != C4JRender::PRIMITIVE_TYPE_TRIANGLE_LIST && - primitiveType != C4JRender::PRIMITIVE_TYPE_QUAD_LIST) { - return 0; - } - - if (count <= 0 || srcBytes == nullptr) - return 0; - - const uint32_t outVertexCount = - (primitiveType == C4JRender::PRIMITIVE_TYPE_TRIANGLE_LIST) - ? static_cast(count) - : static_cast((count / 4) * 6); - if (outVertexCount == 0) - return 0; - - const size_t oldSize = out.size(); - out.resize(oldSize + - static_cast(outVertexCount) * kVertexStridePF3TF2CB4NB4XW1); - uint8_t *dst = out.data() + oldSize; - const size_t sourceStride = - isCompressedVertex ? 16 : kVertexStridePF3TF2CB4NB4XW1; - - auto emitExpandedVertex = [&](int srcVertexIndex) { - const uint8_t *src = - srcBytes + static_cast(srcVertexIndex) * sourceStride; - if (isStandardVertex) { - std::memcpy(dst, src, kVertexStridePF3TF2CB4NB4XW1); - float srcU = 0.0f; - std::memcpy(&srcU, src + 12, sizeof(float)); - srcU = decodeLegacyNoMipmapU(srcU); - std::memcpy(dst + 12, &srcU, sizeof(float)); - // Input color bytes are ABGR in little-endian memory. Convert to RGBA. - const uint8_t srcA = src[20]; - const uint8_t srcB = src[21]; - const uint8_t srcG = src[22]; - const uint8_t srcR = src[23]; - dst[20] = srcR; - dst[21] = srcG; - dst[22] = srcB; - dst[23] = srcA; - if (applyColourMul) { - dst[20] = modulate8(dst[20], colourMulR); - dst[21] = modulate8(dst[21], colourMulG); - dst[22] = modulate8(dst[22], colourMulB); - dst[23] = modulate8(dst[23], colourMulA); - } - dst += kVertexStridePF3TF2CB4NB4XW1; - return; - } - - const int16_t *s = reinterpret_cast(src); - const float x = static_cast(s[0]) / 1024.0f; - const float y = static_cast(s[1]) / 1024.0f; - const float z = static_cast(s[2]) / 1024.0f; - const uint16_t encodedColour = static_cast(s[3]); - const uint16_t packed565 = static_cast(encodedColour + 32768u); - const float u = static_cast(s[4]) / 8192.0f; - const float v = static_cast(s[5]) / 8192.0f; - uint8_t r = 255, g = 255, b = 255, a = 255; - unpack565ToRGBA(packed565, r, g, b, a); - if (applyColourMul) { - r = modulate8(r, colourMulR); - g = modulate8(g, colourMulG); - b = modulate8(b, colourMulB); - a = modulate8(a, colourMulA); - } - - BootstrapVertex outVertex = {x, y, z, u, v, r, g, b, a, 0, 0, 0, 0, 0}; - std::memcpy(dst, &outVertex, sizeof(outVertex)); - dst += sizeof(outVertex); - }; - - if (primitiveType == C4JRender::PRIMITIVE_TYPE_TRIANGLE_LIST) { - for (int i = 0; i < count; ++i) { - emitExpandedVertex(i); - } - } else { - const int quadCount = count / 4; - for (int q = 0; q < quadCount; ++q) { - const int base = q * 4; - emitExpandedVertex(base + 0); - emitExpandedVertex(base + 1); - emitExpandedVertex(base + 2); - emitExpandedVertex(base + 2); - emitExpandedVertex(base + 3); - emitExpandedVertex(base + 0); - } - } - - return outVertexCount; -} - -static void queuePreparedExpandedDrawWithMvp(const uint8_t *vertexBytes, - uint32_t vertexCount, - const float *mvp) { - if (!g_vkInitialized || vertexBytes == nullptr || vertexCount == 0) - return; - - const size_t firstVertex = - g_vkFrameVertexData.size() / kVertexStridePF3TF2CB4NB4XW1; - const size_t oldSize = g_vkFrameVertexData.size(); - const size_t addBytes = - static_cast(vertexCount) * kVertexStridePF3TF2CB4NB4XW1; - g_vkFrameVertexData.resize(oldSize + addBytes); - std::memcpy(g_vkFrameVertexData.data() + oldSize, vertexBytes, addBytes); - - VulkanQueuedDraw draw = {}; - draw.firstVertex = static_cast(firstVertex); - draw.vertexCount = vertexCount; - draw.depthTestEnable = g_vkStateDepthTestEnable; - draw.depthWriteEnable = g_vkStateDepthWriteEnable; - draw.depthCompareOp = g_vkStateDepthCompareOp; - draw.blendEnable = g_vkStateBlendEnable; - draw.srcBlendFactor = g_vkStateSrcBlendFactor; - draw.dstBlendFactor = g_vkStateDstBlendFactor; - draw.colorWriteMask = g_vkStateColorWriteMask; - draw.cullEnable = g_vkStateCullEnable; - draw.cullClockwise = g_vkStateCullClockwise; - std::memcpy(draw.blendConstants, g_vkStateBlendConstants, - sizeof(draw.blendConstants)); - draw.descriptorSet = resolveTextureDescriptorSet(g_vkStateTextureId); - draw.alphaTestEnable = g_vkStateAlphaTestEnable; - draw.alphaFunc = g_vkStateAlphaFunc; - draw.alphaRef = g_vkStateAlphaRef; - if (mvp != nullptr) { - std::memcpy(draw.mvp, mvp, sizeof(draw.mvp)); - } else { - mat4_identity(draw.mvp); - } - - g_vkQueuedDraws.push_back(draw); -} - -void C4JRender::DrawVertices(ePrimitiveType primitiveType, int count, - void *dataIn, eVertexType vType, - ePixelShaderType psType) { - if (!g_vkInitialized || count <= 0 || dataIn == nullptr) - return; - - if (primitiveType != PRIMITIVE_TYPE_TRIANGLE_LIST && - primitiveType != PRIMITIVE_TYPE_QUAD_LIST) - return; - - const bool isStandardVertex = - (vType == VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1 || - vType == VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_TEXGEN || - vType == VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_LIT); - const bool isCompressedVertex = (vType == VERTEX_TYPE_COMPRESSED); - if (!isStandardVertex && !isCompressedVertex) - return; - - if (g_vkIsRecordingCommandList && g_vkRecordingCommandListIndex >= 0) { - RecordedDrawCall call = {}; - call.primitiveType = primitiveType; - call.count = count; - call.vType = vType; - call.psType = psType; - call.preparedVertexCount = 0; - call.hasLocalModelMatrix = true; - const float *recordModelView = MatrixGet(GL_MODELVIEW_MATRIX); - if (recordModelView != nullptr && g_vkRecordingBaseModelValid) { - // Display-list semantics: matrix ops inside the list are relative to - // matrix state at CBuffStart, not absolute compile-time camera state. - mat4_multiply(call.localModelMatrix, g_vkRecordingBaseModelInv, - recordModelView); - } else { - mat4_identity(call.localModelMatrix); - } - call.useCapturedState = g_vkRecordingHasStateChanges; - call.depthTestEnable = g_vkStateDepthTestEnable; - call.depthWriteEnable = g_vkStateDepthWriteEnable; - call.depthCompareOp = g_vkStateDepthCompareOp; - call.blendEnable = g_vkStateBlendEnable; - call.srcBlendFactor = g_vkStateSrcBlendFactor; - call.dstBlendFactor = g_vkStateDstBlendFactor; - call.colorWriteMask = g_vkStateColorWriteMask; - call.cullEnable = g_vkStateCullEnable; - call.cullClockwise = g_vkStateCullClockwise; - std::memcpy(call.blendConstants, g_vkStateBlendConstants, - sizeof(call.blendConstants)); - // bug we hit: replaying compile-time textureId broke chunk textures. - call.captureTextureState = g_vkRecordingHasTextureStateChanges; - call.textureId = g_vkStateTextureId; - call.captureAlphaState = g_vkRecordingHasAlphaStateChanges; - call.alphaTestEnable = g_vkStateAlphaTestEnable; - call.alphaFunc = g_vkStateAlphaFunc; - call.alphaRef = g_vkStateAlphaRef; - const size_t sourceStride = - isCompressedVertex ? 16 : kVertexStridePF3TF2CB4NB4XW1; - call.vertexData.resize(static_cast(count) * sourceStride); - std::memcpy(call.vertexData.data(), dataIn, call.vertexData.size()); - call.preparedVertexCount = expandVertexStreamToBootstrap( - call.preparedVertexData, primitiveType, count, vType, - call.vertexData.data(), false, 1.0f, 1.0f, 1.0f, 1.0f); - g_vkRecordingScratch.push_back(std::move(call)); - return; - } - - const uint8_t *srcBytes = static_cast(dataIn); - const size_t firstVertex = - g_vkFrameVertexData.size() / kVertexStridePF3TF2CB4NB4XW1; - const bool applyColourMul = !vkColourMulIsIdentity(); - uint32_t outVertexCount = expandVertexStreamToBootstrap( - g_vkFrameVertexData, primitiveType, count, vType, srcBytes, applyColourMul, - g_vkStateColour[0], g_vkStateColour[1], g_vkStateColour[2], - g_vkStateColour[3]); - if (outVertexCount == 0) - return; - - VulkanQueuedDraw draw = {}; - draw.firstVertex = static_cast(firstVertex); - draw.vertexCount = outVertexCount; - draw.depthTestEnable = g_vkStateDepthTestEnable; - draw.depthWriteEnable = g_vkStateDepthWriteEnable; - draw.depthCompareOp = g_vkStateDepthCompareOp; - draw.blendEnable = g_vkStateBlendEnable; - draw.srcBlendFactor = g_vkStateSrcBlendFactor; - draw.dstBlendFactor = g_vkStateDstBlendFactor; - draw.colorWriteMask = g_vkStateColorWriteMask; - draw.cullEnable = g_vkStateCullEnable; - draw.cullClockwise = g_vkStateCullClockwise; - std::memcpy(draw.blendConstants, g_vkStateBlendConstants, - sizeof(draw.blendConstants)); - draw.descriptorSet = resolveTextureDescriptorSet(g_vkStateTextureId); - draw.alphaTestEnable = g_vkStateAlphaTestEnable; - draw.alphaFunc = g_vkStateAlphaFunc; - draw.alphaRef = g_vkStateAlphaRef; - - const float *modelView = MatrixGet(GL_MODELVIEW_MATRIX); - const float *projection = MatrixGet(GL_PROJECTION_MATRIX); - if (modelView != nullptr && projection != nullptr) { - mat4_multiply(draw.mvp, projection, modelView); - } else { - mat4_identity(draw.mvp); - } - - g_vkQueuedDraws.push_back(draw); -} -void C4JRender::DrawVertexBuffer(ePrimitiveType, int, void *, eVertexType, - ePixelShaderType) {} - -// ============================================================================ -// Command buffers -// ============================================================================ -void C4JRender::CBuffLockStaticCreations() {} -int C4JRender::CBuffCreate(int count) { - if (count <= 0) - count = 1; - std::lock_guard commandListsLock(g_vkCommandListsMutex); - int first = g_nextCommandBufferId; - g_nextCommandBufferId += count; - for (int i = 0; i < count; ++i) { - g_vkCommandLists[first + i] = std::make_shared>(); - } - return first; -} -void C4JRender::CBuffDelete(int first, int count) { - if (count <= 0) - count = 1; - { - std::lock_guard commandListsLock(g_vkCommandListsMutex); - for (int i = 0; i < count; ++i) { - g_vkCommandLists.erase(first + i); - } - } - if (g_vkIsRecordingCommandList && - g_vkRecordingCommandListIndex >= first && - g_vkRecordingCommandListIndex < (first + count)) { - g_vkIsRecordingCommandList = false; - g_vkRecordingCommandListIndex = -1; - g_vkRecordingScratch.clear(); - g_vkRecordingHasStateChanges = false; - g_vkRecordingHasTextureStateChanges = false; - g_vkRecordingHasAlphaStateChanges = false; - g_vkRecordingBaseModelValid = false; - } -} -void C4JRender::CBuffStart(int index, bool full) { - (void)full; - ensureThreadLocalMatrixStacksInitialised(); - g_vkIsRecordingCommandList = true; - g_vkRecordingCommandListIndex = index; - { - std::lock_guard commandListsLock(g_vkCommandListsMutex); - if (g_vkCommandLists.find(index) == g_vkCommandLists.end()) - g_vkCommandLists[index] = std::make_shared>(); - } - g_vkRecordingScratch.clear(); - g_vkRecordingHasStateChanges = false; - g_vkRecordingHasTextureStateChanges = false; - g_vkRecordingHasAlphaStateChanges = false; - const float *baseModel = MatrixGet(GL_MODELVIEW_MATRIX); - if (baseModel != nullptr) { - g_vkRecordingBaseModelValid = - mat4_inverse(g_vkRecordingBaseModelInv, baseModel); - } else { - g_vkRecordingBaseModelValid = false; - } - if (!g_vkRecordingBaseModelValid) { - mat4_identity(g_vkRecordingBaseModelInv); - g_vkRecordingBaseModelValid = true; - } -} -void C4JRender::CBuffClear(int index) { - std::lock_guard commandListsLock(g_vkCommandListsMutex); - g_vkCommandLists[index] = std::make_shared>(); -} -int C4JRender::CBuffSize(int index) { - // old renderers used this as allocator pressure. - // for vulkan, returning big values here made chunk rebuild stall. - if (index == -1) { - return 0; - } - - size_t bytes = 0; - std::lock_guard commandListsLock(g_vkCommandListsMutex); - auto it = g_vkCommandLists.find(index); - if (it != g_vkCommandLists.end() && it->second) { - for (const auto &call : *it->second) { - bytes += call.vertexData.size(); - } - } - return static_cast(bytes); -} -void C4JRender::CBuffEnd() { - if (g_vkIsRecordingCommandList && g_vkRecordingCommandListIndex >= 0) { - std::lock_guard commandListsLock(g_vkCommandListsMutex); - g_vkCommandLists[g_vkRecordingCommandListIndex] = - std::make_shared>( - std::move(g_vkRecordingScratch)); - g_vkRecordingScratch.clear(); - } else { - g_vkRecordingScratch.clear(); - } - g_vkIsRecordingCommandList = false; - g_vkRecordingCommandListIndex = -1; - g_vkRecordingHasStateChanges = false; - g_vkRecordingHasTextureStateChanges = false; - g_vkRecordingHasAlphaStateChanges = false; - g_vkRecordingBaseModelValid = false; -} -bool C4JRender::CBuffCall(int index, bool) { - std::shared_ptr> calls; - { - std::lock_guard commandListsLock(g_vkCommandListsMutex); - auto it = g_vkCommandLists.find(index); - if (it == g_vkCommandLists.end()) - return false; - calls = it->second; - } - if (!calls) - return false; - - ensureThreadLocalMatrixStacksInitialised(); - float callSiteModelView[16]; - const float *callSiteModelViewPtr = MatrixGet(GL_MODELVIEW_MATRIX); - if (callSiteModelViewPtr != nullptr) { - std::memcpy(callSiteModelView, callSiteModelViewPtr, - sizeof(callSiteModelView)); - } else { - mat4_identity(callSiteModelView); - } - float callSiteProjection[16]; - const float *callSiteProjectionPtr = MatrixGet(GL_PROJECTION_MATRIX); - if (callSiteProjectionPtr != nullptr) { - std::memcpy(callSiteProjection, callSiteProjectionPtr, - sizeof(callSiteProjection)); - } else { - mat4_identity(callSiteProjection); - } - - const bool wasRecording = g_vkIsRecordingCommandList; - const int oldRecordingIndex = g_vkRecordingCommandListIndex; - const bool oldDepthTestEnable = g_vkStateDepthTestEnable; - const bool oldDepthWriteEnable = g_vkStateDepthWriteEnable; - const VkCompareOp oldDepthCompareOp = g_vkStateDepthCompareOp; - const bool oldBlendEnable = g_vkStateBlendEnable; - const VkBlendFactor oldSrcBlendFactor = g_vkStateSrcBlendFactor; - const VkBlendFactor oldDstBlendFactor = g_vkStateDstBlendFactor; - const VkColorComponentFlags oldColorWriteMask = g_vkStateColorWriteMask; - const bool oldCullEnable = g_vkStateCullEnable; - const bool oldCullClockwise = g_vkStateCullClockwise; - const int oldTextureId = g_vkStateTextureId; - const bool oldAlphaTestEnable = g_vkStateAlphaTestEnable; - const int oldAlphaFunc = g_vkStateAlphaFunc; - const float oldAlphaRef = g_vkStateAlphaRef; - float oldBlendConstants[4] = {g_vkStateBlendConstants[0], - g_vkStateBlendConstants[1], - g_vkStateBlendConstants[2], - g_vkStateBlendConstants[3]}; - g_vkIsRecordingCommandList = false; - g_vkRecordingCommandListIndex = -1; - - for (const RecordedDrawCall &call : *calls) { - if (call.vertexData.empty() || call.count <= 0) - continue; - if (call.useCapturedState) { - g_vkStateDepthTestEnable = call.depthTestEnable; - g_vkStateDepthWriteEnable = call.depthWriteEnable; - g_vkStateDepthCompareOp = call.depthCompareOp; - g_vkStateBlendEnable = call.blendEnable; - g_vkStateSrcBlendFactor = call.srcBlendFactor; - g_vkStateDstBlendFactor = call.dstBlendFactor; - g_vkStateColorWriteMask = call.colorWriteMask; - g_vkStateCullEnable = call.cullEnable; - g_vkStateCullClockwise = call.cullClockwise; - std::memcpy(g_vkStateBlendConstants, call.blendConstants, - sizeof(call.blendConstants)); - } - if (call.captureTextureState) { - // only change texture state if this draw recorded a TextureBind. - g_vkStateTextureId = call.textureId; - } - if (call.captureAlphaState) { - g_vkStateAlphaTestEnable = call.alphaTestEnable; - g_vkStateAlphaFunc = call.alphaFunc; - g_vkStateAlphaRef = call.alphaRef; - } - const bool canUsePrepared = - vkColourMulIsIdentity() && (call.preparedVertexCount > 0) && - !call.preparedVertexData.empty(); - if (canUsePrepared) { - float drawMvp[16]; - if (call.hasLocalModelMatrix) { - float combinedModelView[16]; - mat4_multiply(combinedModelView, callSiteModelView, call.localModelMatrix); - mat4_multiply(drawMvp, callSiteProjection, combinedModelView); - } else { - mat4_multiply(drawMvp, callSiteProjection, callSiteModelView); - } - queuePreparedExpandedDrawWithMvp(call.preparedVertexData.data(), - call.preparedVertexCount, drawMvp); - } else { - if (call.hasLocalModelMatrix) { - float combinedModelView[16]; - mat4_multiply(combinedModelView, callSiteModelView, call.localModelMatrix); - std::memcpy(g_matStacks[GL_MODELVIEW].stack[g_matStacks[GL_MODELVIEW].top], - combinedModelView, sizeof(combinedModelView)); - } - DrawVertices(call.primitiveType, call.count, - const_cast(call.vertexData.data()), call.vType, - call.psType); - if (call.hasLocalModelMatrix) { - std::memcpy(g_matStacks[GL_MODELVIEW].stack[g_matStacks[GL_MODELVIEW].top], - callSiteModelView, sizeof(callSiteModelView)); - } - } - } - - g_vkStateDepthTestEnable = oldDepthTestEnable; - g_vkStateDepthWriteEnable = oldDepthWriteEnable; - g_vkStateDepthCompareOp = oldDepthCompareOp; - g_vkStateBlendEnable = oldBlendEnable; - g_vkStateSrcBlendFactor = oldSrcBlendFactor; - g_vkStateDstBlendFactor = oldDstBlendFactor; - g_vkStateColorWriteMask = oldColorWriteMask; - g_vkStateCullEnable = oldCullEnable; - g_vkStateCullClockwise = oldCullClockwise; - g_vkStateTextureId = oldTextureId; - g_vkStateAlphaTestEnable = oldAlphaTestEnable; - g_vkStateAlphaFunc = oldAlphaFunc; - g_vkStateAlphaRef = oldAlphaRef; - std::memcpy(g_vkStateBlendConstants, oldBlendConstants, - sizeof(oldBlendConstants)); - g_vkIsRecordingCommandList = wasRecording; - g_vkRecordingCommandListIndex = oldRecordingIndex; - return true; -} -void C4JRender::CBuffTick() {} -void C4JRender::CBuffDeferredModeStart() {} -void C4JRender::CBuffDeferredModeEnd() {} - -// ============================================================================ -// Textures -// ============================================================================ -int C4JRender::TextureCreate() { - const int id = g_nextTextureId++; - VulkanTexture tex = {}; - tex.id = id; - tex.width = 0; - tex.height = 0; - tex.mipLevels = 1; - tex.image = VK_NULL_HANDLE; - tex.memory = VK_NULL_HANDLE; - tex.imageView = VK_NULL_HANDLE; - tex.sampler = VK_NULL_HANDLE; - tex.descriptorSet = VK_NULL_HANDLE; - tex.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - tex.minFilter = GL_NEAREST; - tex.magFilter = GL_NEAREST; - tex.wrapS = GL_REPEAT; - tex.wrapT = GL_REPEAT; - tex.requestedMipLevels = 1; - tex.pendingUpload = false; - tex.levelData.clear(); - g_vkTextures[id] = tex; - return id; -} - -void C4JRender::TextureFree(int idx) { - if (idx <= 0) - return; - auto it = g_vkTextures.find(idx); - if (it == g_vkTextures.end()) - return; - destroyTextureGpuResources(it->second); - g_vkTextures.erase(it); - if (g_vkStateTextureId == idx) - g_vkStateTextureId = -1; - if (g_vkStateVertexTextureId == idx) - g_vkStateVertexTextureId = -1; -} - -void C4JRender::TextureBind(int idx) { - g_vkStateTextureId = idx; - // record that this bind happened, so replay uses it. - if (g_vkIsRecordingCommandList) - g_vkRecordingHasTextureStateChanges = true; - if (idx < 0) - return; - auto it = g_vkTextures.find(idx); - if (it == g_vkTextures.end()) - return; - if (it->second.pendingUpload) { - ensureTextureUploadedFromCache(it->second); - } else if (it->second.image != VK_NULL_HANDLE && - it->second.descriptorSet == VK_NULL_HANDLE && - hasTextureUploadContext()) { - updateTextureDescriptorSet(it->second); - } -} - -void C4JRender::TextureBindVertex(int idx) { g_vkStateVertexTextureId = idx; } - -void C4JRender::TextureSetTextureLevels(int levels) { - if (levels < 1) - levels = 1; - if (levels > 16) - levels = 16; - g_vkPendingTextureLevels = levels; - auto it = g_vkTextures.find(g_vkStateTextureId); - if (it != g_vkTextures.end()) { - it->second.requestedMipLevels = static_cast(levels); - } -} - -int C4JRender::TextureGetTextureLevels() { - auto it = g_vkTextures.find(g_vkStateTextureId); - if (it != g_vkTextures.end() && it->second.mipLevels > 0) { - return static_cast(it->second.mipLevels); - } - return g_vkPendingTextureLevels; -} - -void C4JRender::TextureData(int width, int height, void *data, int level, - eTextureFormat format) { - (void)format; - if (g_vkStateTextureId < 0 || width <= 0 || height <= 0 || data == nullptr || - level < 0) { - return; - } - - auto it = g_vkTextures.find(g_vkStateTextureId); - if (it == g_vkTextures.end()) { - return; - } - - VulkanTexture &tex = it->second; - const uint32_t uploadLevel = static_cast(level); - cacheTextureLevelPixels(tex, uploadLevel, static_cast(width), - static_cast(height), data); - - uint32_t requestedLevels = - static_cast((g_vkPendingTextureLevels > 0) ? g_vkPendingTextureLevels - : 1); - if (requestedLevels <= uploadLevel) - requestedLevels = uploadLevel + 1; - tex.requestedMipLevels = requestedLevels; - - if (!hasTextureUploadContext()) { - return; - } - - if (ensureTextureUploadedFromCache(tex)) { - return; - } - - uint32_t targetLevels = - static_cast((g_vkPendingTextureLevels > 0) ? g_vkPendingTextureLevels - : 1); - if (targetLevels <= uploadLevel) - targetLevels = uploadLevel + 1; - - uint32_t baseWidth = static_cast(width); - uint32_t baseHeight = static_cast(height); - if (uploadLevel > 0) { - baseWidth = baseWidth << uploadLevel; - baseHeight = baseHeight << uploadLevel; - } - - const bool needsRecreate = - (tex.image == VK_NULL_HANDLE) || (tex.width != baseWidth) || - (tex.height != baseHeight) || (tex.mipLevels != targetLevels); - if (needsRecreate) { - if (!createTextureImageAndView(tex, baseWidth, baseHeight, targetLevels)) - return; - } - - if (uploadTextureRegionImmediate(tex, uploadLevel, 0, 0, - static_cast(width), - static_cast(height), data)) { - tex.pendingUpload = false; - } -} - -void C4JRender::TextureDataUpdate(int xoffset, int yoffset, int width, int height, - void *data, int level) { - if (g_vkStateTextureId < 0 || width <= 0 || height <= 0 || data == nullptr || - level < 0 || xoffset < 0 || yoffset < 0) { - return; - } - - auto it = g_vkTextures.find(g_vkStateTextureId); - if (it == g_vkTextures.end()) { - return; - } - - VulkanTexture &tex = it->second; - const uint32_t uploadLevel = static_cast(level); - const uint32_t uWidth = static_cast(width); - const uint32_t uHeight = static_cast(height); - const uint32_t uX = static_cast(xoffset); - const uint32_t uY = static_cast(yoffset); - bool cachedPatch = patchTextureLevelPixels(tex, uploadLevel, uX, uY, uWidth, - uHeight, data); - if (!cachedPatch && xoffset == 0 && yoffset == 0) { - cacheTextureLevelPixels(tex, uploadLevel, uWidth, uHeight, data); - cachedPatch = true; - } - - if (!hasTextureUploadContext()) { - if (!cachedPatch) { - TextureData(width, height, data, level, TEXTURE_FORMAT_RxGyBzAw); - } - return; - } - - if (cachedPatch && ensureTextureUploadedFromCache(tex)) { - return; - } - - if (tex.image == VK_NULL_HANDLE || uploadLevel >= tex.mipLevels) { - TextureData(width, height, data, level, TEXTURE_FORMAT_RxGyBzAw); - return; - } - - uploadTextureRegionImmediate( - tex, uploadLevel, uX, uY, uWidth, uHeight, data); - tex.pendingUpload = false; -} - -void C4JRender::TextureSetParam(int param, int value) { - auto it = g_vkTextures.find(g_vkStateTextureId); - if (it == g_vkTextures.end()) - return; - - VulkanTexture &tex = it->second; - switch (param) { - case GL_TEXTURE_MIN_FILTER: - tex.minFilter = value; - break; - case GL_TEXTURE_MAG_FILTER: - tex.magFilter = value; - break; - case GL_TEXTURE_WRAP_S: - tex.wrapS = value; - break; - case GL_TEXTURE_WRAP_T: - tex.wrapT = value; - break; - default: - return; - } - if (tex.image != VK_NULL_HANDLE) { - recreateTextureSampler(tex); - } -} -void C4JRender::TextureDynamicUpdateStart() {} -void C4JRender::TextureDynamicUpdateEnd() {} - -HRESULT C4JRender::LoadTextureData(const char *szFilename, - D3DXIMAGE_INFO *pSrcInfo, int **ppDataOut) { - if (!szFilename || !pSrcInfo || !ppDataOut) - return E_INVALIDARG; - - *ppDataOut = nullptr; - pSrcInfo->Width = 0; - pSrcInfo->Height = 0; - - HRESULT coHr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); - const bool shouldUninit = SUCCEEDED(coHr); - if (coHr == RPC_E_CHANGED_MODE) - coHr = S_OK; - if (FAILED(coHr)) - return coHr; - - std::wstring wpath = toWidePath(szFilename); - if (wpath.empty()) { - if (shouldUninit) - CoUninitialize(); - return E_INVALIDARG; - } - - IWICImagingFactory *factory = nullptr; - IWICBitmapDecoder *decoder = nullptr; - IWICBitmapFrameDecode *frame = nullptr; - - HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, - CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory)); - if (SUCCEEDED(hr)) { - hr = factory->CreateDecoderFromFilename(wpath.c_str(), nullptr, - GENERIC_READ, - WICDecodeMetadataCacheOnLoad, - &decoder); - } - if (SUCCEEDED(hr)) { - hr = decoder->GetFrame(0, &frame); - } - if (SUCCEEDED(hr)) { - hr = decodeFrameToArgb(frame, pSrcInfo, ppDataOut); - } - - SafeReleaseCOM(frame); - SafeReleaseCOM(decoder); - SafeReleaseCOM(factory); - if (shouldUninit) - CoUninitialize(); - return hr; -} - -HRESULT C4JRender::LoadTextureData(BYTE *pbData, DWORD dwBytes, - D3DXIMAGE_INFO *pSrcInfo, int **ppDataOut) { - if (!pbData || dwBytes == 0 || !pSrcInfo || !ppDataOut) - return E_INVALIDARG; - - *ppDataOut = nullptr; - pSrcInfo->Width = 0; - pSrcInfo->Height = 0; - - HRESULT coHr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); - const bool shouldUninit = SUCCEEDED(coHr); - if (coHr == RPC_E_CHANGED_MODE) - coHr = S_OK; - if (FAILED(coHr)) - return coHr; - - IWICImagingFactory *factory = nullptr; - IWICStream *stream = nullptr; - IWICBitmapDecoder *decoder = nullptr; - IWICBitmapFrameDecode *frame = nullptr; - - HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, - CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory)); - if (SUCCEEDED(hr)) { - hr = factory->CreateStream(&stream); - } - if (SUCCEEDED(hr)) { - hr = stream->InitializeFromMemory(pbData, dwBytes); - } - if (SUCCEEDED(hr)) { - hr = factory->CreateDecoderFromStream(stream, nullptr, - WICDecodeMetadataCacheOnLoad, - &decoder); - } - if (SUCCEEDED(hr)) { - hr = decoder->GetFrame(0, &frame); - } - if (SUCCEEDED(hr)) { - hr = decodeFrameToArgb(frame, pSrcInfo, ppDataOut); - } - - SafeReleaseCOM(frame); - SafeReleaseCOM(decoder); - SafeReleaseCOM(stream); - SafeReleaseCOM(factory); - if (shouldUninit) - CoUninitialize(); - return hr; -} -HRESULT C4JRender::SaveTextureData(const char *, D3DXIMAGE_INFO *, int *) { - return E_NOTIMPL; -} -HRESULT C4JRender::SaveTextureDataToMemory(void *, int, int *, int, int, - int *) { - return E_NOTIMPL; -} -void C4JRender::TextureGetStats() {} -void *C4JRender::TextureGetTexture(int) { return nullptr; } - -// ============================================================================ -// State control -// ============================================================================ -void C4JRender::StateSetColour(float r, float g, float b, float a) { - auto clamp01 = [](float value) { - if (value < 0.0f) - return 0.0f; - if (value > 1.0f) - return 1.0f; - return value; - }; - g_vkStateColour[0] = clamp01(r); - g_vkStateColour[1] = clamp01(g); - g_vkStateColour[2] = clamp01(b); - g_vkStateColour[3] = clamp01(a); -} -void C4JRender::StateSetDepthMask(bool enable) { - g_vkStateDepthWriteEnable = enable; - if (g_vkIsRecordingCommandList) - g_vkRecordingHasStateChanges = true; -} -void C4JRender::StateSetBlendEnable(bool enable) { - g_vkStateBlendEnable = enable; - if (g_vkIsRecordingCommandList) - g_vkRecordingHasStateChanges = true; -} -void C4JRender::StateSetBlendFunc(int src, int dst) { - g_vkStateSrcBlendFactor = mapBlendFactorToVk(src); - g_vkStateDstBlendFactor = mapBlendFactorToVk(dst); - if (g_vkIsRecordingCommandList) - g_vkRecordingHasStateChanges = true; -} -void C4JRender::StateSetBlendFactor(unsigned int colour) { - const float a = static_cast((colour >> 24) & 0xff) / 255.0f; - const float r = static_cast((colour >> 16) & 0xff) / 255.0f; - const float g = static_cast((colour >> 8) & 0xff) / 255.0f; - const float b = static_cast(colour & 0xff) / 255.0f; - g_vkStateBlendConstants[0] = r; - g_vkStateBlendConstants[1] = g; - g_vkStateBlendConstants[2] = b; - g_vkStateBlendConstants[3] = a; - if (g_vkIsRecordingCommandList) - g_vkRecordingHasStateChanges = true; -} -void C4JRender::StateSetAlphaFunc(int func, float param) { - g_vkStateAlphaFunc = func; - g_vkStateAlphaRef = param; - if (g_vkIsRecordingCommandList) - g_vkRecordingHasAlphaStateChanges = true; -} -void C4JRender::StateSetDepthFunc(int func) { - g_vkStateDepthCompareOp = mapDepthFuncToVk(func); - if (g_vkIsRecordingCommandList) - g_vkRecordingHasStateChanges = true; -} -void C4JRender::StateSetFaceCull(bool enable) { - g_vkStateCullEnable = enable; - if (g_vkIsRecordingCommandList) - g_vkRecordingHasStateChanges = true; -} -void C4JRender::StateSetFaceCullCW(bool enable) { - g_vkStateCullClockwise = enable; - if (g_vkIsRecordingCommandList) - g_vkRecordingHasStateChanges = true; -} -void C4JRender::StateSetLineWidth(float) {} -void C4JRender::StateSetWriteEnable(bool red, bool green, bool blue, bool alpha) { - VkColorComponentFlags mask = 0; - if (red) - mask |= VK_COLOR_COMPONENT_R_BIT; - if (green) - mask |= VK_COLOR_COMPONENT_G_BIT; - if (blue) - mask |= VK_COLOR_COMPONENT_B_BIT; - if (alpha) - mask |= VK_COLOR_COMPONENT_A_BIT; - g_vkStateColorWriteMask = mask; - if (g_vkIsRecordingCommandList) - g_vkRecordingHasStateChanges = true; -} -void C4JRender::StateSetDepthTestEnable(bool enable) { - g_vkStateDepthTestEnable = enable; - if (g_vkIsRecordingCommandList) - g_vkRecordingHasStateChanges = true; -} -void C4JRender::StateSetAlphaTestEnable(bool enable) { - g_vkStateAlphaTestEnable = enable; - if (g_vkIsRecordingCommandList) - g_vkRecordingHasAlphaStateChanges = true; -} -void C4JRender::StateSetDepthSlopeAndBias(float, float) {} -void C4JRender::StateSetFogEnable(bool) {} -void C4JRender::StateSetFogMode(int) {} -void C4JRender::StateSetFogNearDistance(float) {} -void C4JRender::StateSetFogFarDistance(float) {} -void C4JRender::StateSetFogDensity(float) {} -void C4JRender::StateSetFogColour(float, float, float) {} -void C4JRender::StateSetLightingEnable(bool) {} -void C4JRender::StateSetVertexTextureUV(float, float) {} -void C4JRender::StateSetLightColour(int, float, float, float) {} -void C4JRender::StateSetLightAmbientColour(float, float, float) {} -void C4JRender::StateSetLightDirection(int, float, float, float) {} -void C4JRender::StateSetLightEnable(int, bool) {} -void C4JRender::StateSetViewport(eViewportType) {} -void C4JRender::StateSetEnableViewportClipPlanes(bool) {} -void C4JRender::StateSetTexGenCol(int, float, float, float, float, bool) {} -void C4JRender::StateSetStencil(int, uint8_t, uint8_t, uint8_t) {} -void C4JRender::StateSetForceLOD(int) {} - -// ============================================================================ -// Events + PLM -// ============================================================================ -void C4JRender::BeginEvent(LPCWSTR) {} -void C4JRender::EndEvent() {} -void C4JRender::Suspend() {} -bool C4JRender::Suspended() { return false; } -void C4JRender::Resume() {} diff --git a/Minecraft.Client/Windows64/VulkanTriangleShaders.inl b/Minecraft.Client/Windows64/VulkanTriangleShaders.inl deleted file mode 100644 index 311898ff..00000000 --- a/Minecraft.Client/Windows64/VulkanTriangleShaders.inl +++ /dev/null @@ -1,145 +0,0 @@ -// Auto-generated SPIR-V for DrawVertices textured + alpha-test pipeline. -static const uint32_t kTriangleVertSpv[] = { - 0x07230203, 0x00010000, 0x0008000b, 0x0000003f, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, - 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, - 0x000b000f, 0x00000000, 0x00000004, 0x6e69616d, 0x00000000, 0x00000015, 0x00000031, 0x00000037, - 0x00000039, 0x0000003b, 0x0000003d, 0x00030003, 0x00000002, 0x000001c2, 0x00040005, 0x00000004, - 0x6e69616d, 0x00000000, 0x00030005, 0x00000009, 0x00736f70, 0x00060005, 0x0000000b, 0x68737550, - 0x736e6f43, 0x746e6174, 0x00000073, 0x00040006, 0x0000000b, 0x00000000, 0x0070766d, 0x00060006, - 0x0000000b, 0x00000001, 0x68706c61, 0x61745361, 0x00006574, 0x00030005, 0x0000000d, 0x00006370, - 0x00040005, 0x00000015, 0x6f506e69, 0x00000073, 0x00060005, 0x0000002f, 0x505f6c67, 0x65567265, - 0x78657472, 0x00000000, 0x00060006, 0x0000002f, 0x00000000, 0x505f6c67, 0x7469736f, 0x006e6f69, - 0x00070006, 0x0000002f, 0x00000001, 0x505f6c67, 0x746e696f, 0x657a6953, 0x00000000, 0x00070006, - 0x0000002f, 0x00000002, 0x435f6c67, 0x4470696c, 0x61747369, 0x0065636e, 0x00070006, 0x0000002f, - 0x00000003, 0x435f6c67, 0x446c6c75, 0x61747369, 0x0065636e, 0x00030005, 0x00000031, 0x00000000, - 0x00030005, 0x00000037, 0x00565576, 0x00040005, 0x00000039, 0x56556e69, 0x00000000, 0x00040005, - 0x0000003b, 0x6c6f4376, 0x0000726f, 0x00040005, 0x0000003d, 0x6f436e69, 0x00726f6c, 0x00030047, - 0x0000000b, 0x00000002, 0x00040048, 0x0000000b, 0x00000000, 0x00000005, 0x00050048, 0x0000000b, - 0x00000000, 0x00000007, 0x00000010, 0x00050048, 0x0000000b, 0x00000000, 0x00000023, 0x00000000, - 0x00050048, 0x0000000b, 0x00000001, 0x00000023, 0x00000040, 0x00040047, 0x00000015, 0x0000001e, - 0x00000000, 0x00030047, 0x0000002f, 0x00000002, 0x00050048, 0x0000002f, 0x00000000, 0x0000000b, - 0x00000000, 0x00050048, 0x0000002f, 0x00000001, 0x0000000b, 0x00000001, 0x00050048, 0x0000002f, - 0x00000002, 0x0000000b, 0x00000003, 0x00050048, 0x0000002f, 0x00000003, 0x0000000b, 0x00000004, - 0x00040047, 0x00000037, 0x0000001e, 0x00000000, 0x00040047, 0x00000039, 0x0000001e, 0x00000001, - 0x00040047, 0x0000003b, 0x0000001e, 0x00000001, 0x00040047, 0x0000003d, 0x0000001e, 0x00000002, - 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00030016, 0x00000006, 0x00000020, - 0x00040017, 0x00000007, 0x00000006, 0x00000004, 0x00040020, 0x00000008, 0x00000007, 0x00000007, - 0x00040018, 0x0000000a, 0x00000007, 0x00000004, 0x0004001e, 0x0000000b, 0x0000000a, 0x00000007, - 0x00040020, 0x0000000c, 0x00000009, 0x0000000b, 0x0004003b, 0x0000000c, 0x0000000d, 0x00000009, - 0x00040015, 0x0000000e, 0x00000020, 0x00000001, 0x0004002b, 0x0000000e, 0x0000000f, 0x00000000, - 0x00040020, 0x00000010, 0x00000009, 0x0000000a, 0x00040017, 0x00000013, 0x00000006, 0x00000003, - 0x00040020, 0x00000014, 0x00000001, 0x00000013, 0x0004003b, 0x00000014, 0x00000015, 0x00000001, - 0x0004002b, 0x00000006, 0x00000017, 0x3f800000, 0x00040015, 0x0000001d, 0x00000020, 0x00000000, - 0x0004002b, 0x0000001d, 0x0000001e, 0x00000001, 0x00040020, 0x0000001f, 0x00000007, 0x00000006, - 0x0004002b, 0x0000001d, 0x00000024, 0x00000002, 0x0004002b, 0x0000001d, 0x00000027, 0x00000003, - 0x0004002b, 0x00000006, 0x0000002b, 0x3f000000, 0x0004001c, 0x0000002e, 0x00000006, 0x0000001e, - 0x0006001e, 0x0000002f, 0x00000007, 0x00000006, 0x0000002e, 0x0000002e, 0x00040020, 0x00000030, - 0x00000003, 0x0000002f, 0x0004003b, 0x00000030, 0x00000031, 0x00000003, 0x00040020, 0x00000033, - 0x00000003, 0x00000007, 0x00040017, 0x00000035, 0x00000006, 0x00000002, 0x00040020, 0x00000036, - 0x00000003, 0x00000035, 0x0004003b, 0x00000036, 0x00000037, 0x00000003, 0x00040020, 0x00000038, - 0x00000001, 0x00000035, 0x0004003b, 0x00000038, 0x00000039, 0x00000001, 0x0004003b, 0x00000033, - 0x0000003b, 0x00000003, 0x00040020, 0x0000003c, 0x00000001, 0x00000007, 0x0004003b, 0x0000003c, - 0x0000003d, 0x00000001, 0x00050036, 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, - 0x00000005, 0x0004003b, 0x00000008, 0x00000009, 0x00000007, 0x00050041, 0x00000010, 0x00000011, - 0x0000000d, 0x0000000f, 0x0004003d, 0x0000000a, 0x00000012, 0x00000011, 0x0004003d, 0x00000013, - 0x00000016, 0x00000015, 0x00050051, 0x00000006, 0x00000018, 0x00000016, 0x00000000, 0x00050051, - 0x00000006, 0x00000019, 0x00000016, 0x00000001, 0x00050051, 0x00000006, 0x0000001a, 0x00000016, - 0x00000002, 0x00070050, 0x00000007, 0x0000001b, 0x00000018, 0x00000019, 0x0000001a, 0x00000017, - 0x00050091, 0x00000007, 0x0000001c, 0x00000012, 0x0000001b, 0x0003003e, 0x00000009, 0x0000001c, - 0x00050041, 0x0000001f, 0x00000020, 0x00000009, 0x0000001e, 0x0004003d, 0x00000006, 0x00000021, - 0x00000020, 0x0004007f, 0x00000006, 0x00000022, 0x00000021, 0x00050041, 0x0000001f, 0x00000023, - 0x00000009, 0x0000001e, 0x0003003e, 0x00000023, 0x00000022, 0x00050041, 0x0000001f, 0x00000025, - 0x00000009, 0x00000024, 0x0004003d, 0x00000006, 0x00000026, 0x00000025, 0x00050041, 0x0000001f, - 0x00000028, 0x00000009, 0x00000027, 0x0004003d, 0x00000006, 0x00000029, 0x00000028, 0x00050081, - 0x00000006, 0x0000002a, 0x00000026, 0x00000029, 0x00050085, 0x00000006, 0x0000002c, 0x0000002a, - 0x0000002b, 0x00050041, 0x0000001f, 0x0000002d, 0x00000009, 0x00000024, 0x0003003e, 0x0000002d, - 0x0000002c, 0x0004003d, 0x00000007, 0x00000032, 0x00000009, 0x00050041, 0x00000033, 0x00000034, - 0x00000031, 0x0000000f, 0x0003003e, 0x00000034, 0x00000032, 0x0004003d, 0x00000035, 0x0000003a, - 0x00000039, 0x0003003e, 0x00000037, 0x0000003a, 0x0004003d, 0x00000007, 0x0000003e, 0x0000003d, - 0x0003003e, 0x0000003b, 0x0000003e, 0x000100fd, 0x00010038, -}; - -static const uint32_t kTriangleFragSpv[] = { - 0x07230203, 0x00010000, 0x0008000b, 0x00000077, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, - 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, - 0x0008000f, 0x00000004, 0x00000004, 0x6e69616d, 0x00000000, 0x0000004a, 0x0000004e, 0x00000075, - 0x00030010, 0x00000004, 0x00000007, 0x00030003, 0x00000002, 0x000001c2, 0x00040005, 0x00000004, - 0x6e69616d, 0x00000000, 0x00080005, 0x0000000f, 0x68706c61, 0x73655461, 0x73615074, 0x31662873, - 0x3b31693b, 0x003b3166, 0x00030005, 0x0000000c, 0x00000061, 0x00040005, 0x0000000d, 0x636e7566, - 0x00000000, 0x00040005, 0x0000000e, 0x56666572, 0x00006c61, 0x00040005, 0x00000042, 0x6f6c6f63, - 0x00000072, 0x00040005, 0x00000046, 0x78655475, 0x00000000, 0x00030005, 0x0000004a, 0x00565576, - 0x00040005, 0x0000004e, 0x6c6f4376, 0x0000726f, 0x00060005, 0x00000052, 0x68737550, 0x736e6f43, - 0x746e6174, 0x00000073, 0x00040006, 0x00000052, 0x00000000, 0x0070766d, 0x00060006, 0x00000052, - 0x00000001, 0x68706c61, 0x61745361, 0x00006574, 0x00030005, 0x00000054, 0x00006370, 0x00040005, - 0x0000005f, 0x636e7566, 0x00000000, 0x00040005, 0x00000065, 0x61726170, 0x0000006d, 0x00040005, - 0x00000069, 0x61726170, 0x0000006d, 0x00040005, 0x0000006b, 0x61726170, 0x0000006d, 0x00050005, - 0x00000075, 0x4374756f, 0x726f6c6f, 0x00000000, 0x00040047, 0x00000046, 0x00000021, 0x00000000, - 0x00040047, 0x00000046, 0x00000022, 0x00000000, 0x00040047, 0x0000004a, 0x0000001e, 0x00000000, - 0x00040047, 0x0000004e, 0x0000001e, 0x00000001, 0x00030047, 0x00000052, 0x00000002, 0x00040048, - 0x00000052, 0x00000000, 0x00000005, 0x00050048, 0x00000052, 0x00000000, 0x00000007, 0x00000010, - 0x00050048, 0x00000052, 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x00000052, 0x00000001, - 0x00000023, 0x00000040, 0x00040047, 0x00000075, 0x0000001e, 0x00000000, 0x00020013, 0x00000002, - 0x00030021, 0x00000003, 0x00000002, 0x00030016, 0x00000006, 0x00000020, 0x00040020, 0x00000007, - 0x00000007, 0x00000006, 0x00040015, 0x00000008, 0x00000020, 0x00000001, 0x00040020, 0x00000009, - 0x00000007, 0x00000008, 0x00020014, 0x0000000a, 0x00060021, 0x0000000b, 0x0000000a, 0x00000007, - 0x00000009, 0x00000007, 0x0003002a, 0x0000000a, 0x0000001c, 0x0004002b, 0x00000006, 0x00000026, - 0x3b808081, 0x00030029, 0x0000000a, 0x0000003b, 0x00040017, 0x00000040, 0x00000006, 0x00000004, - 0x00040020, 0x00000041, 0x00000007, 0x00000040, 0x00090019, 0x00000043, 0x00000006, 0x00000001, - 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0003001b, 0x00000044, 0x00000043, - 0x00040020, 0x00000045, 0x00000000, 0x00000044, 0x0004003b, 0x00000045, 0x00000046, 0x00000000, - 0x00040017, 0x00000048, 0x00000006, 0x00000002, 0x00040020, 0x00000049, 0x00000001, 0x00000048, - 0x0004003b, 0x00000049, 0x0000004a, 0x00000001, 0x00040020, 0x0000004d, 0x00000001, 0x00000040, - 0x0004003b, 0x0000004d, 0x0000004e, 0x00000001, 0x00040018, 0x00000051, 0x00000040, 0x00000004, - 0x0004001e, 0x00000052, 0x00000051, 0x00000040, 0x00040020, 0x00000053, 0x00000009, 0x00000052, - 0x0004003b, 0x00000053, 0x00000054, 0x00000009, 0x0004002b, 0x00000008, 0x00000055, 0x00000001, - 0x00040015, 0x00000056, 0x00000020, 0x00000000, 0x0004002b, 0x00000056, 0x00000057, 0x00000000, - 0x00040020, 0x00000058, 0x00000009, 0x00000006, 0x0004002b, 0x00000006, 0x0000005b, 0x3f000000, - 0x0004002b, 0x00000056, 0x00000060, 0x00000002, 0x0004002b, 0x00000056, 0x00000066, 0x00000003, - 0x0004002b, 0x00000056, 0x0000006c, 0x00000001, 0x00040020, 0x00000074, 0x00000003, 0x00000040, - 0x0004003b, 0x00000074, 0x00000075, 0x00000003, 0x00050036, 0x00000002, 0x00000004, 0x00000000, - 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x00000041, 0x00000042, 0x00000007, 0x0004003b, - 0x00000009, 0x0000005f, 0x00000007, 0x0004003b, 0x00000007, 0x00000065, 0x00000007, 0x0004003b, - 0x00000009, 0x00000069, 0x00000007, 0x0004003b, 0x00000007, 0x0000006b, 0x00000007, 0x0004003d, - 0x00000044, 0x00000047, 0x00000046, 0x0004003d, 0x00000048, 0x0000004b, 0x0000004a, 0x00050057, - 0x00000040, 0x0000004c, 0x00000047, 0x0000004b, 0x0004003d, 0x00000040, 0x0000004f, 0x0000004e, - 0x00050085, 0x00000040, 0x00000050, 0x0000004c, 0x0000004f, 0x0003003e, 0x00000042, 0x00000050, - 0x00060041, 0x00000058, 0x00000059, 0x00000054, 0x00000055, 0x00000057, 0x0004003d, 0x00000006, - 0x0000005a, 0x00000059, 0x000500ba, 0x0000000a, 0x0000005c, 0x0000005a, 0x0000005b, 0x000300f7, - 0x0000005e, 0x00000000, 0x000400fa, 0x0000005c, 0x0000005d, 0x0000005e, 0x000200f8, 0x0000005d, - 0x00060041, 0x00000058, 0x00000061, 0x00000054, 0x00000055, 0x00000060, 0x0004003d, 0x00000006, - 0x00000062, 0x00000061, 0x00050081, 0x00000006, 0x00000063, 0x00000062, 0x0000005b, 0x0004006e, - 0x00000008, 0x00000064, 0x00000063, 0x0003003e, 0x0000005f, 0x00000064, 0x00050041, 0x00000007, - 0x00000067, 0x00000042, 0x00000066, 0x0004003d, 0x00000006, 0x00000068, 0x00000067, 0x0003003e, - 0x00000065, 0x00000068, 0x0004003d, 0x00000008, 0x0000006a, 0x0000005f, 0x0003003e, 0x00000069, - 0x0000006a, 0x00060041, 0x00000058, 0x0000006d, 0x00000054, 0x00000055, 0x0000006c, 0x0004003d, - 0x00000006, 0x0000006e, 0x0000006d, 0x0003003e, 0x0000006b, 0x0000006e, 0x00070039, 0x0000000a, - 0x0000006f, 0x0000000f, 0x00000065, 0x00000069, 0x0000006b, 0x000400a8, 0x0000000a, 0x00000070, - 0x0000006f, 0x000300f7, 0x00000072, 0x00000000, 0x000400fa, 0x00000070, 0x00000071, 0x00000072, - 0x000200f8, 0x00000071, 0x000100fc, 0x000200f8, 0x00000072, 0x000200f9, 0x0000005e, 0x000200f8, - 0x0000005e, 0x0004003d, 0x00000040, 0x00000076, 0x00000042, 0x0003003e, 0x00000075, 0x00000076, - 0x000100fd, 0x00010038, 0x00050036, 0x0000000a, 0x0000000f, 0x00000000, 0x0000000b, 0x00030037, - 0x00000007, 0x0000000c, 0x00030037, 0x00000009, 0x0000000d, 0x00030037, 0x00000007, 0x0000000e, - 0x000200f8, 0x00000010, 0x0004003d, 0x00000008, 0x00000011, 0x0000000d, 0x000300f7, 0x0000001b, - 0x00000000, 0x001300fb, 0x00000011, 0x0000001a, 0x00000001, 0x00000012, 0x00000002, 0x00000013, - 0x00000003, 0x00000014, 0x00000004, 0x00000015, 0x00000005, 0x00000016, 0x00000006, 0x00000017, - 0x00000007, 0x00000018, 0x00000008, 0x00000019, 0x000200f8, 0x0000001a, 0x000200fe, 0x0000003b, - 0x000200f8, 0x00000012, 0x000200fe, 0x0000001c, 0x000200f8, 0x00000013, 0x0004003d, 0x00000006, - 0x0000001e, 0x0000000c, 0x0004003d, 0x00000006, 0x0000001f, 0x0000000e, 0x000500b8, 0x0000000a, - 0x00000020, 0x0000001e, 0x0000001f, 0x000200fe, 0x00000020, 0x000200f8, 0x00000014, 0x0004003d, - 0x00000006, 0x00000022, 0x0000000c, 0x0004003d, 0x00000006, 0x00000023, 0x0000000e, 0x00050083, - 0x00000006, 0x00000024, 0x00000022, 0x00000023, 0x0006000c, 0x00000006, 0x00000025, 0x00000001, - 0x00000004, 0x00000024, 0x000500bc, 0x0000000a, 0x00000027, 0x00000025, 0x00000026, 0x000200fe, - 0x00000027, 0x000200f8, 0x00000015, 0x0004003d, 0x00000006, 0x00000029, 0x0000000c, 0x0004003d, - 0x00000006, 0x0000002a, 0x0000000e, 0x000500bc, 0x0000000a, 0x0000002b, 0x00000029, 0x0000002a, - 0x000200fe, 0x0000002b, 0x000200f8, 0x00000016, 0x0004003d, 0x00000006, 0x0000002d, 0x0000000c, - 0x0004003d, 0x00000006, 0x0000002e, 0x0000000e, 0x000500ba, 0x0000000a, 0x0000002f, 0x0000002d, - 0x0000002e, 0x000200fe, 0x0000002f, 0x000200f8, 0x00000017, 0x0004003d, 0x00000006, 0x00000031, - 0x0000000c, 0x0004003d, 0x00000006, 0x00000032, 0x0000000e, 0x00050083, 0x00000006, 0x00000033, - 0x00000031, 0x00000032, 0x0006000c, 0x00000006, 0x00000034, 0x00000001, 0x00000004, 0x00000033, - 0x000500ba, 0x0000000a, 0x00000035, 0x00000034, 0x00000026, 0x000200fe, 0x00000035, 0x000200f8, - 0x00000018, 0x0004003d, 0x00000006, 0x00000037, 0x0000000c, 0x0004003d, 0x00000006, 0x00000038, - 0x0000000e, 0x000500be, 0x0000000a, 0x00000039, 0x00000037, 0x00000038, 0x000200fe, 0x00000039, - 0x000200f8, 0x00000019, 0x000200fe, 0x0000003b, 0x000200f8, 0x0000001b, 0x000100ff, 0x00010038, - -}; - diff --git a/Minecraft.Client/Windows64/VulkanUIBridge.h b/Minecraft.Client/Windows64/VulkanUIBridge.h deleted file mode 100644 index b1b5b1f5..00000000 --- a/Minecraft.Client/Windows64/VulkanUIBridge.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include - -void VulkanSubmitIggyOverlayBGRA(int width, int height, const void *pixels, - size_t bytes); diff --git a/Minecraft.Client/Windows64/VulkanUIShaders.inl b/Minecraft.Client/Windows64/VulkanUIShaders.inl deleted file mode 100644 index 6444dce7..00000000 --- a/Minecraft.Client/Windows64/VulkanUIShaders.inl +++ /dev/null @@ -1,87 +0,0 @@ -// Auto-generated SPIR-V for Vulkan UI composite pipeline. -static const uint32_t kUiCompositeVertSpv[] = { - 0x07230203, 0x00010000, 0x000d000b, 0x0000003f, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, - 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, - 0x000b000f, 0x00000000, 0x00000004, 0x6e69616d, 0x00000000, 0x00000015, 0x00000031, 0x00000037, - 0x00000039, 0x0000003b, 0x0000003d, 0x00030003, 0x00000002, 0x000001c2, 0x000a0004, 0x475f4c47, - 0x4c474f4f, 0x70635f45, 0x74735f70, 0x5f656c79, 0x656e696c, 0x7269645f, 0x69746365, 0x00006576, - 0x00080004, 0x475f4c47, 0x4c474f4f, 0x6e695f45, 0x64756c63, 0x69645f65, 0x74636572, 0x00657669, - 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00030005, 0x00000009, 0x00736f70, 0x00040005, - 0x0000000b, 0x68737550, 0x00000000, 0x00040006, 0x0000000b, 0x00000000, 0x0070766d, 0x00030005, - 0x0000000d, 0x00006370, 0x00040005, 0x00000015, 0x6f506e69, 0x00000073, 0x00060005, 0x0000002f, - 0x505f6c67, 0x65567265, 0x78657472, 0x00000000, 0x00060006, 0x0000002f, 0x00000000, 0x505f6c67, - 0x7469736f, 0x006e6f69, 0x00070006, 0x0000002f, 0x00000001, 0x505f6c67, 0x746e696f, 0x657a6953, - 0x00000000, 0x00070006, 0x0000002f, 0x00000002, 0x435f6c67, 0x4470696c, 0x61747369, 0x0065636e, - 0x00070006, 0x0000002f, 0x00000003, 0x435f6c67, 0x446c6c75, 0x61747369, 0x0065636e, 0x00030005, - 0x00000031, 0x00000000, 0x00030005, 0x00000037, 0x00565576, 0x00040005, 0x00000039, 0x56556e69, - 0x00000000, 0x00040005, 0x0000003b, 0x6c6f4376, 0x0000726f, 0x00040005, 0x0000003d, 0x6f436e69, - 0x00726f6c, 0x00030047, 0x0000000b, 0x00000002, 0x00040048, 0x0000000b, 0x00000000, 0x00000005, - 0x00050048, 0x0000000b, 0x00000000, 0x00000007, 0x00000010, 0x00050048, 0x0000000b, 0x00000000, - 0x00000023, 0x00000000, 0x00040047, 0x00000015, 0x0000001e, 0x00000000, 0x00030047, 0x0000002f, - 0x00000002, 0x00050048, 0x0000002f, 0x00000000, 0x0000000b, 0x00000000, 0x00050048, 0x0000002f, - 0x00000001, 0x0000000b, 0x00000001, 0x00050048, 0x0000002f, 0x00000002, 0x0000000b, 0x00000003, - 0x00050048, 0x0000002f, 0x00000003, 0x0000000b, 0x00000004, 0x00040047, 0x00000037, 0x0000001e, - 0x00000000, 0x00040047, 0x00000039, 0x0000001e, 0x00000001, 0x00040047, 0x0000003b, 0x0000001e, - 0x00000001, 0x00040047, 0x0000003d, 0x0000001e, 0x00000002, 0x00020013, 0x00000002, 0x00030021, - 0x00000003, 0x00000002, 0x00030016, 0x00000006, 0x00000020, 0x00040017, 0x00000007, 0x00000006, - 0x00000004, 0x00040020, 0x00000008, 0x00000007, 0x00000007, 0x00040018, 0x0000000a, 0x00000007, - 0x00000004, 0x0003001e, 0x0000000b, 0x0000000a, 0x00040020, 0x0000000c, 0x00000009, 0x0000000b, - 0x0004003b, 0x0000000c, 0x0000000d, 0x00000009, 0x00040015, 0x0000000e, 0x00000020, 0x00000001, - 0x0004002b, 0x0000000e, 0x0000000f, 0x00000000, 0x00040020, 0x00000010, 0x00000009, 0x0000000a, - 0x00040017, 0x00000013, 0x00000006, 0x00000003, 0x00040020, 0x00000014, 0x00000001, 0x00000013, - 0x0004003b, 0x00000014, 0x00000015, 0x00000001, 0x0004002b, 0x00000006, 0x00000017, 0x3f800000, - 0x00040015, 0x0000001d, 0x00000020, 0x00000000, 0x0004002b, 0x0000001d, 0x0000001e, 0x00000001, - 0x00040020, 0x0000001f, 0x00000007, 0x00000006, 0x0004002b, 0x0000001d, 0x00000024, 0x00000002, - 0x0004002b, 0x0000001d, 0x00000027, 0x00000003, 0x0004002b, 0x00000006, 0x0000002b, 0x3f000000, - 0x0004001c, 0x0000002e, 0x00000006, 0x0000001e, 0x0006001e, 0x0000002f, 0x00000007, 0x00000006, - 0x0000002e, 0x0000002e, 0x00040020, 0x00000030, 0x00000003, 0x0000002f, 0x0004003b, 0x00000030, - 0x00000031, 0x00000003, 0x00040020, 0x00000033, 0x00000003, 0x00000007, 0x00040017, 0x00000035, - 0x00000006, 0x00000002, 0x00040020, 0x00000036, 0x00000003, 0x00000035, 0x0004003b, 0x00000036, - 0x00000037, 0x00000003, 0x00040020, 0x00000038, 0x00000001, 0x00000035, 0x0004003b, 0x00000038, - 0x00000039, 0x00000001, 0x0004003b, 0x00000033, 0x0000003b, 0x00000003, 0x00040020, 0x0000003c, - 0x00000001, 0x00000007, 0x0004003b, 0x0000003c, 0x0000003d, 0x00000001, 0x00050036, 0x00000002, - 0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x00000008, 0x00000009, - 0x00000007, 0x00050041, 0x00000010, 0x00000011, 0x0000000d, 0x0000000f, 0x0004003d, 0x0000000a, - 0x00000012, 0x00000011, 0x0004003d, 0x00000013, 0x00000016, 0x00000015, 0x00050051, 0x00000006, - 0x00000018, 0x00000016, 0x00000000, 0x00050051, 0x00000006, 0x00000019, 0x00000016, 0x00000001, - 0x00050051, 0x00000006, 0x0000001a, 0x00000016, 0x00000002, 0x00070050, 0x00000007, 0x0000001b, - 0x00000018, 0x00000019, 0x0000001a, 0x00000017, 0x00050091, 0x00000007, 0x0000001c, 0x00000012, - 0x0000001b, 0x0003003e, 0x00000009, 0x0000001c, 0x00050041, 0x0000001f, 0x00000020, 0x00000009, - 0x0000001e, 0x0004003d, 0x00000006, 0x00000021, 0x00000020, 0x0004007f, 0x00000006, 0x00000022, - 0x00000021, 0x00050041, 0x0000001f, 0x00000023, 0x00000009, 0x0000001e, 0x0003003e, 0x00000023, - 0x00000022, 0x00050041, 0x0000001f, 0x00000025, 0x00000009, 0x00000024, 0x0004003d, 0x00000006, - 0x00000026, 0x00000025, 0x00050041, 0x0000001f, 0x00000028, 0x00000009, 0x00000027, 0x0004003d, - 0x00000006, 0x00000029, 0x00000028, 0x00050081, 0x00000006, 0x0000002a, 0x00000026, 0x00000029, - 0x00050085, 0x00000006, 0x0000002c, 0x0000002a, 0x0000002b, 0x00050041, 0x0000001f, 0x0000002d, - 0x00000009, 0x00000024, 0x0003003e, 0x0000002d, 0x0000002c, 0x0004003d, 0x00000007, 0x00000032, - 0x00000009, 0x00050041, 0x00000033, 0x00000034, 0x00000031, 0x0000000f, 0x0003003e, 0x00000034, - 0x00000032, 0x0004003d, 0x00000035, 0x0000003a, 0x00000039, 0x0003003e, 0x00000037, 0x0000003a, - 0x0004003d, 0x00000007, 0x0000003e, 0x0000003d, 0x0003003e, 0x0000003b, 0x0000003e, 0x000100fd, - 0x00010038 -}; - -static const uint32_t kUiCompositeFragSpv[] = { - 0x07230203, 0x00010000, 0x000d000b, 0x00000018, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, - 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, - 0x0008000f, 0x00000004, 0x00000004, 0x6e69616d, 0x00000000, 0x00000009, 0x00000011, 0x00000015, - 0x00030010, 0x00000004, 0x00000007, 0x00030003, 0x00000002, 0x000001c2, 0x000a0004, 0x475f4c47, - 0x4c474f4f, 0x70635f45, 0x74735f70, 0x5f656c79, 0x656e696c, 0x7269645f, 0x69746365, 0x00006576, - 0x00080004, 0x475f4c47, 0x4c474f4f, 0x6e695f45, 0x64756c63, 0x69645f65, 0x74636572, 0x00657669, - 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00050005, 0x00000009, 0x4374756f, 0x726f6c6f, - 0x00000000, 0x00040005, 0x0000000d, 0x78655475, 0x00000000, 0x00030005, 0x00000011, 0x00565576, - 0x00040005, 0x00000015, 0x6c6f4376, 0x0000726f, 0x00040047, 0x00000009, 0x0000001e, 0x00000000, - 0x00040047, 0x0000000d, 0x00000021, 0x00000000, 0x00040047, 0x0000000d, 0x00000022, 0x00000000, - 0x00040047, 0x00000011, 0x0000001e, 0x00000000, 0x00040047, 0x00000015, 0x0000001e, 0x00000001, - 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00030016, 0x00000006, 0x00000020, - 0x00040017, 0x00000007, 0x00000006, 0x00000004, 0x00040020, 0x00000008, 0x00000003, 0x00000007, - 0x0004003b, 0x00000008, 0x00000009, 0x00000003, 0x00090019, 0x0000000a, 0x00000006, 0x00000001, - 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0003001b, 0x0000000b, 0x0000000a, - 0x00040020, 0x0000000c, 0x00000000, 0x0000000b, 0x0004003b, 0x0000000c, 0x0000000d, 0x00000000, - 0x00040017, 0x0000000f, 0x00000006, 0x00000002, 0x00040020, 0x00000010, 0x00000001, 0x0000000f, - 0x0004003b, 0x00000010, 0x00000011, 0x00000001, 0x00040020, 0x00000014, 0x00000001, 0x00000007, - 0x0004003b, 0x00000014, 0x00000015, 0x00000001, 0x00050036, 0x00000002, 0x00000004, 0x00000000, - 0x00000003, 0x000200f8, 0x00000005, 0x0004003d, 0x0000000b, 0x0000000e, 0x0000000d, 0x0004003d, - 0x0000000f, 0x00000012, 0x00000011, 0x00050057, 0x00000007, 0x00000013, 0x0000000e, 0x00000012, - 0x0004003d, 0x00000007, 0x00000016, 0x00000015, 0x00050085, 0x00000007, 0x00000017, 0x00000013, - 0x00000016, 0x0003003e, 0x00000009, 0x00000017, 0x000100fd, 0x00010038 -};