From d43c566fa29bbc0da1534aea236d54ee5ca104b8 Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Fri, 14 Dec 2018 15:24:21 -0500 Subject: Fix memory leaks around slang-test (#757) * Remove circular reference to renderer on Vk & D3D12 DescriptorSetImpl * Refactor Stbi image loading such that memory is correctly freed when goes out of scope. Added Crt memory dump at termination. Reduced erroneous reporting by scoping TestContext. * Used capitalized acronym for STBImage to keep Tim happy. * Split out TestReporter - to just handle reporting test results Split out Options Made TestContext hold options, and the reporter Removed remaining memory leaks. * Small optimization for rawWrite, such that it directly writes over print.. * Improve comments on TestCategorySet * Fix typos in TestCategorySet --- tools/slang-test/options.cpp | 245 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 tools/slang-test/options.cpp (limited to 'tools/slang-test/options.cpp') diff --git a/tools/slang-test/options.cpp b/tools/slang-test/options.cpp new file mode 100644 index 000000000..cb6adbc6f --- /dev/null +++ b/tools/slang-test/options.cpp @@ -0,0 +1,245 @@ +// test-context.cpp +#include "options.h" + +#include "os.h" +#include "../../source/core/slang-string-util.h" + +#include +#include +#include + +using namespace Slang; + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! CategorySet !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +TestCategory* TestCategorySet::add(String const& name, TestCategory* parent) +{ + RefPtr category(new TestCategory); + category->name = name; + category->parent = parent; + + m_categoryMap.Add(name, category); + return category; +} + +TestCategory* TestCategorySet::find(String const& name) +{ + RefPtr category; + if (!m_categoryMap.TryGetValue(name, category)) + { + return nullptr; + } + return category; +} + +TestCategory* TestCategorySet::findOrError(String const& name) +{ + TestCategory* category = find(name); + if (!category) + { + AppContext::getStdError().print("error: unknown test category name '%s'\n", name.Buffer()); + } + return category; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! Options !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +/* static */Result Options::parse(int argc, char** argv, TestCategorySet* categorySet, Slang::WriterHelper stdError, Options* optionsOut) +{ + // Reset the options + *optionsOut = Options(); + + List positionalArgs; + + int argCount = argc; + char const* const* argCursor = argv; + char const* const* argEnd = argCursor + argCount; + + // first argument is the application name + if (argCursor != argEnd) + { + optionsOut->appName = *argCursor++; + } + + // now iterate over arguments to collect options + while (argCursor != argEnd) + { + char const* arg = *argCursor++; + if (arg[0] != '-') + { + positionalArgs.Add(arg); + continue; + } + + if (strcmp(arg, "--") == 0) + { + while (argCursor != argEnd) + { + positionalArgs.Add(*argCursor++); + } + break; + } + + if (strcmp(arg, "-bindir") == 0) + { + if (argCursor == argEnd) + { + stdError.print("error: expected operand for '%s'\n", arg); + return SLANG_FAIL; + } + optionsOut->binDir = *argCursor++; + } + else if (strcmp(arg, "-useexes") == 0) + { + optionsOut->useExes = true; + } + else if (strcmp(arg, "-v") == 0) + { + optionsOut->shouldBeVerbose = true; + } + else if (strcmp(arg, "-generate-hlsl-baselines") == 0) + { + optionsOut->generateHLSLBaselines = true; + } + else if (strcmp(arg, "-release") == 0) + { + // Assumed to be handle by .bat file that called us + } + else if (strcmp(arg, "-debug") == 0) + { + // Assumed to be handle by .bat file that called us + } + else if (strcmp(arg, "-configuration") == 0) + { + if (argCursor == argEnd) + { + stdError.print("error: expected operand for '%s'\n", arg); + return SLANG_FAIL; + } + argCursor++; + // Assumed to be handle by .bat file that called us + } + else if (strcmp(arg, "-platform") == 0) + { + if (argCursor == argEnd) + { + stdError.print("error: expected operand for '%s'\n", arg); + return SLANG_FAIL; + } + argCursor++; + // Assumed to be handle by .bat file that called us + } + else if (strcmp(arg, "-appveyor") == 0) + { + optionsOut->outputMode = TestOutputMode::AppVeyor; + optionsOut->dumpOutputOnFailure = true; + } + else if (strcmp(arg, "-travis") == 0) + { + optionsOut->outputMode = TestOutputMode::Travis; + optionsOut->dumpOutputOnFailure = true; + } + else if (strcmp(arg, "-xunit") == 0) + { + optionsOut->outputMode = TestOutputMode::XUnit; + } + else if (strcmp(arg, "-xunit2") == 0) + { + optionsOut->outputMode = TestOutputMode::XUnit2; + } + else if (strcmp(arg, "-teamcity") == 0) + { + optionsOut->outputMode = TestOutputMode::TeamCity; + } + else if (strcmp(arg, "-category") == 0) + { + if (argCursor == argEnd) + { + stdError.print("error: expected operand for '%s'\n", arg); + return SLANG_FAIL; + } + auto category = categorySet->findOrError(*argCursor++); + if (category) + { + optionsOut->includeCategories.Add(category, category); + } + } + else if (strcmp(arg, "-exclude") == 0) + { + if (argCursor == argEnd) + { + stdError.print("error: expected operand for '%s'\n", arg); + return SLANG_FAIL; + } + auto category = categorySet->findOrError(*argCursor++); + if (category) + { + optionsOut->excludeCategories.Add(category, category); + } + } + else if (strcmp(arg, "-api") == 0) + { + if (argCursor == argEnd) + { + stdError.print("error: expecting an api expression (eg 'vk+dx12' or '+dx11') '%s'\n", arg); + return SLANG_FAIL; + } + const char* apiList = *argCursor++; + + SlangResult res = RenderApiUtil::parseApiFlags(UnownedStringSlice(apiList), optionsOut->enabledApis, &optionsOut->enabledApis); + if (SLANG_FAILED(res)) + { + stdError.print("error: unable to parse api expression '%s'\n", apiList); + return res; + } + } + else if (strcmp(arg, "-synthesizedTestApi") == 0) + { + if (argCursor == argEnd) + { + stdError.print("error: expected an api expression (eg 'vk+dx12' or '+dx11') '%s'\n", arg); + return SLANG_FAIL; + } + const char* apiList = *argCursor++; + + SlangResult res = RenderApiUtil::parseApiFlags(UnownedStringSlice(apiList), optionsOut->synthesizedTestApis, &optionsOut->synthesizedTestApis); + if (SLANG_FAILED(res)) + { + stdError.print("error: unable to parse api expression '%s'\n", apiList); + return res; + } + } + else + { + stdError.print("unknown option '%s'\n", arg); + return SLANG_FAIL; + } + } + + { + // Find out what apis are available + const int availableApis = RenderApiUtil::getAvailableApis(); + // Only allow apis we know are available + optionsOut->enabledApis &= availableApis; + + // Can only synth for apis that are available + optionsOut->synthesizedTestApis &= optionsOut->enabledApis; + } + + + // first positional argument is source shader path + if (positionalArgs.Count()) + { + optionsOut->testPrefix = positionalArgs[0]; + positionalArgs.RemoveAt(0); + } + + // any remaining arguments represent an error + if (positionalArgs.Count() != 0) + { + stdError.print("unexpected arguments\n"); + return SLANG_FAIL; + } + + return SLANG_OK; +} -- cgit v1.2.3