From 2b0482e1c629b08acdaa56fedc44bec11097d9ab Mon Sep 17 00:00:00 2001 From: Kearwood Date: Sun, 9 Aug 2020 20:34:21 -0700 Subject: [PATCH] KrDataBlock::Append(std::string) now correctly handles null termination in output KRDataBlock when used multiple times. Implemented KrGetResourceData API call. KrCompileAllShaders now outputs shader compilation logs as a KRResource. kraken_convert now outputs shader compile logs when failure occurs. --- kraken/KRContext.cpp | 48 ++++++++++++++++++++++++++++++++++++-- kraken/KRContext.h | 1 + kraken/KRDataBlock.cpp | 19 ++++++++++++--- kraken/KRShaderManager.cpp | 10 +++++--- kraken/KRShaderManager.h | 4 +++- kraken/kraken.cpp | 9 +++++++ kraken/public/kraken.h | 15 ++++++++++++ tools/convert/main.cpp | 14 +++++++++++ 8 files changed, 111 insertions(+), 9 deletions(-) diff --git a/kraken/KRContext.cpp b/kraken/KRContext.cpp index 37a6869..462d2b8 100755 --- a/kraken/KRContext.cpp +++ b/kraken/KRContext.cpp @@ -449,6 +449,32 @@ KrResult KRContext::unmapResource(const KrUnmapResourceInfo* unmapResourceInfo) return KR_SUCCESS; } +KrResult KRContext::getResourceData(const KrGetResourceDataInfo* getResourceDataInfo, KrGetResourceDataCallback callback) +{ + if (getResourceDataInfo->resourceHandle < 0 || getResourceDataInfo->resourceHandle >= m_resourceMapSize) { + return KR_ERROR_OUT_OF_BOUNDS; + } + // TODO - This will be asynchronous... + KRDataBlock data; + KrGetResourceDataResult result = {}; + if (m_resourceMap[getResourceDataInfo->resourceHandle] == nullptr) { + result.result = KR_ERROR_NOT_MAPPED; + callback(result); + } else if (m_resourceMap[getResourceDataInfo->resourceHandle]->save(data)) { + data.lock(); + result.data = data.getStart(); + result.length = static_cast(data.getSize()); + result.result = KR_SUCCESS; + callback(result); + data.unlock(); + } else { + result.result = KR_ERROR_UNEXPECTED; + callback(result); + } + + return KR_SUCCESS; +} + KrResult KRContext::createScene(const KrCreateSceneInfo* createSceneInfo) { if (createSceneInfo->resourceHandle < 0 || createSceneInfo->resourceHandle >= m_resourceMapSize) { @@ -493,8 +519,26 @@ KrResult KRContext::moveToBundle(const KrMoveToBundleInfo* moveToBundleInfo) return resource->moveToBundle(bundle); } -KrResult KRContext::compileAllShaders(const KrCompileAllShadersInfo* pCompileAllShadersInfo) { - bool success = m_pShaderManager->compileAll(); +KrResult KRContext::compileAllShaders(const KrCompileAllShadersInfo* pCompileAllShadersInfo) +{ + if (pCompileAllShadersInfo->logHandle < -1 || pCompileAllShadersInfo->logHandle >= m_resourceMapSize) { + return KR_ERROR_OUT_OF_BOUNDS; + } + + KRResource* existing_log = m_pUnknownManager->getResource("shader_compile", "log"); + KRUnknown* logResource = nullptr; + if (existing_log != nullptr) { + logResource = dynamic_cast(existing_log); + } + if (logResource == nullptr) { + logResource = new KRUnknown(*this, "shader_compile", "log"); + m_pUnknownManager->add(logResource); + } + if (pCompileAllShadersInfo->logHandle != -1) { + m_resourceMap[pCompileAllShadersInfo->logHandle] = logResource; + } + + bool success = m_pShaderManager->compileAll(logResource); if (success) { // TODO - Save log to a resource return KR_SUCCESS; diff --git a/kraken/KRContext.h b/kraken/KRContext.h index 5dcccb6..035310c 100755 --- a/kraken/KRContext.h +++ b/kraken/KRContext.h @@ -47,6 +47,7 @@ public: KrResult moveToBundle(const KrMoveToBundleInfo* moveToBundleInfo); KrResult loadResource(const KrLoadResourceInfo* loadResourceInfo); KrResult unloadResource(const KrUnloadResourceInfo* unloadResourceInfo); + KrResult getResourceData(const KrGetResourceDataInfo* getResourceDataInfo, KrGetResourceDataCallback callback); KrResult mapResource(const KrMapResourceInfo* mapResourceInfo); KrResult unmapResource(const KrUnmapResourceInfo* unmapResourceInfo); KrResult saveResource(const KrSaveResourceInfo* saveResourceInfo); diff --git a/kraken/KRDataBlock.cpp b/kraken/KRDataBlock.cpp index 7d7c8b7..df3a8b9 100755 --- a/kraken/KRDataBlock.cpp +++ b/kraken/KRDataBlock.cpp @@ -318,11 +318,24 @@ void KRDataBlock::append(KRDataBlock &data) { data.unlock(); } -// Append string to the end of the block, increasing the size of the block and making it read-write. The null terminating character is included +// Append string to the end of the block, increasing the size of the block and making it read-write. The resulting datablock includes a terminating character void KRDataBlock::append(const std::string &s) { - const char *szText = s.c_str(); - append((void *)szText, strlen(szText)+1); + const char* szText = s.c_str(); + size_t text_length = strlen(szText); + size_t prev_size = getSize(); + if (prev_size == 0) { + // First string appended to data block, just memcpy it.. + append((void*)szText, text_length + 1); + } else { + // prev_size includes a null terminating character, don't need to add two. + expand(prev_size + text_length); + lock(); + // Copy new string, overwriting prior null terminating character and + // including new terminating character + memcpy((unsigned char*)m_data + prev_size - 1, szText, text_length + 1); + unlock(); + } } // Save the data to a file. diff --git a/kraken/KRShaderManager.cpp b/kraken/KRShaderManager.cpp index 7701408..b499744 100644 --- a/kraken/KRShaderManager.cpp +++ b/kraken/KRShaderManager.cpp @@ -33,6 +33,8 @@ #include "KREngine-common.h" #include "KRContext.h" #include "KRSourceManager.h" +#include "KRUnknownManager.h" +#include "KRUnknown.h" KRShaderManager::KRShaderManager(KRContext &context) : KRResourceManager(context) , m_initializedGlslang(false) @@ -229,7 +231,7 @@ const TBuiltInResource DefaultTBuiltInResource = { } }; -bool KRShaderManager::compileAll() +bool KRShaderManager::compileAll(KRUnknown* logResource) { bool success = true; if (!m_initializedGlslang) { @@ -285,7 +287,8 @@ bool KRShaderManager::compileAll() program.addShader(&shader); } else { const char* log = shader.getInfoLog(); - printf("Failed to compile shader, %s. Log:\n%s\n", sourceName.c_str(), log); + logResource->getData()->append(log); + logResource->getData()->append("\n"); success = false; } }; @@ -295,7 +298,8 @@ bool KRShaderManager::compileAll() if (!program.link(messages)) { const char* log = program.getInfoLog(); - printf("Link failed. Log:\n%s\n", log); + logResource->getData()->append(log); + logResource->getData()->append("\n"); success = false; } diff --git a/kraken/KRShaderManager.h b/kraken/KRShaderManager.h index 02afd9d..8b31550 100644 --- a/kraken/KRShaderManager.h +++ b/kraken/KRShaderManager.h @@ -40,6 +40,8 @@ #include "KRContextObject.h" #include "KRDataBlock.h" +class KRUnknown; + class KRShaderManager : public KRResourceManager { public: KRShaderManager(KRContext &context); @@ -53,7 +55,7 @@ public: KRShader *load(const std::string &name, const std::string &extension, KRDataBlock *data); KRShader *get(const std::string &name, const std::string &extension); - bool compileAll(); + bool compileAll(KRUnknown* logResource); const unordered_map &get(const std::string &extension); diff --git a/kraken/kraken.cpp b/kraken/kraken.cpp index 2f8d0e1..bc49dd2 100644 --- a/kraken/kraken.cpp +++ b/kraken/kraken.cpp @@ -74,6 +74,15 @@ KrResult KrUnloadResource(const KrUnloadResourceInfo* pUnloadResourceInfo) return sContext->unloadResource(pUnloadResourceInfo); } + +KrResult KrGetResourceData(const KrGetResourceDataInfo* pGetResourceDataInfo, KrGetResourceDataCallback callback) +{ + if (!sContext) { + return KR_ERROR_NOT_INITIALIZED; + } + return sContext->getResourceData(pGetResourceDataInfo, callback); +} + KrResult KrSaveResource(const KrSaveResourceInfo* pSaveResourceInfo) { if (!sContext) { diff --git a/kraken/public/kraken.h b/kraken/public/kraken.h index ad38ca5..93818fd 100644 --- a/kraken/public/kraken.h +++ b/kraken/public/kraken.h @@ -64,6 +64,7 @@ typedef enum { KR_STRUCTURE_TYPE_LOAD_RESOURCE = 0x00010000, KR_STRUCTURE_TYPE_UNLOAD_RESOURCE, + KR_STRUCTURE_TYPE_GET_RESOURCE_DATA, KR_STRUCTURE_TYPE_SAVE_RESOURCE, KR_STRUCTURE_TYPE_MAP_RESOURCE, KR_STRUCTURE_TYPE_UNMAP_RESOURCE, @@ -139,6 +140,19 @@ typedef struct { KrResourceMapIndex resourceHandle; } KrUnloadResourceInfo; +typedef struct { + KrStructureType sType; + KrResourceMapIndex resourceHandle; +} KrGetResourceDataInfo; + +typedef struct { + KrResult result; + void* data; + size_t length; +} KrGetResourceDataResult; + +typedef void (*KrGetResourceDataCallback)(const KrGetResourceDataResult&); + typedef struct { KrStructureType sType; const char* pResourceName; @@ -396,6 +410,7 @@ KrResult KrDeleteWindowSurface(const KrDeleteWindowSurfaceInfo* pDeleteWindowSur KrResult KrLoadResource(const KrLoadResourceInfo* pLoadResourceInfo); KrResult KrUnloadResource(const KrUnloadResourceInfo* pUnloadResourceInfo); +KrResult KrGetResourceData(const KrGetResourceDataInfo* pGetResourceDataInfo, KrGetResourceDataCallback callback); KrResult KrSaveResource(const KrSaveResourceInfo* pSaveResourceInfo); KrResult KrMapResource(const KrMapResourceInfo* pMapResourceInfo); KrResult KrUnmapResource(const KrUnmapResourceInfo* pUnmapResourceInfo); diff --git a/tools/convert/main.cpp b/tools/convert/main.cpp index e1917e1..c6eab6e 100644 --- a/tools/convert/main.cpp +++ b/tools/convert/main.cpp @@ -155,6 +155,20 @@ int main( int argc, char *argv[] ) res = KrCompileAllShaders(&compile_all_shaders_info); if (res != KR_SUCCESS) { printf("[FAIL] (Error %i)\n", res); + KrGetResourceDataInfo get_resource_data_info = {}; + get_resource_data_info.sType = KR_STRUCTURE_TYPE_GET_RESOURCE_DATA; + get_resource_data_info.resourceHandle = ResourceMapping::shader_compile_log; + res = KrGetResourceData(&get_resource_data_info, [](const KrGetResourceDataResult& result) { + // TODO - This will later be asynchronous... Will need to block rest of execution until returned + if (result.result != KR_SUCCESS) { + printf("Failed to get shader compile log. (Error %i)\n", result.result); + } else { + // result.data will be a null terminated string + if (result.data != nullptr) { + printf("Shader compile log:\n%s\n", result.data); + } + } + }); failed = true; } else {