diff options
Diffstat (limited to 'tools/render-test/render-test-main.cpp')
| -rw-r--r-- | tools/render-test/render-test-main.cpp | 453 |
1 files changed, 13 insertions, 440 deletions
diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp index 440ba9c82..5b9621142 100644 --- a/tools/render-test/render-test-main.cpp +++ b/tools/render-test/render-test-main.cpp @@ -21,13 +21,9 @@ #include <stdio.h> #include <stdlib.h> -#define SLANG_PRELUDE_NAMESPACE CPPPrelude -#include "../../prelude/slang-cpp-types.h" - #include "../../source/core/slang-test-tool-util.h" -#include "../../source/core/slang-memory-arena.h" -#include "cpu-memory-binding.h" +#include "cpu-compute-util.h" #define WIN32_LEAN_AND_MEAN #define NOMINMAX @@ -241,436 +237,6 @@ class RenderTestApp int m_numAddedConstantBuffers; ///< Constant buffers can be added to the binding directly. Will be added at the end. }; -// Entry point name to use for vertex/fragment shader -static const char vertexEntryPointName[] = "vertexMain"; -static const char fragmentEntryPointName[] = "fragmentMain"; -static const char computeEntryPointName[] = "computeMain"; - -static SlangResult _readSource(const String& inSourcePath, List<char>& outSourceText) -{ - // Read in the source code - FILE* sourceFile = fopen(inSourcePath.getBuffer(), "rb"); - if (!sourceFile) - { - fprintf(stderr, "error: failed to open '%s' for reading\n", inSourcePath.getBuffer()); - return SLANG_FAIL; - } - fseek(sourceFile, 0, SEEK_END); - size_t sourceSize = ftell(sourceFile); - fseek(sourceFile, 0, SEEK_SET); - - outSourceText.setCount(sourceSize + 1); - fread(outSourceText.getBuffer(), sourceSize, 1, sourceFile); - fclose(sourceFile); - outSourceText[sourceSize] = 0; - - return SLANG_OK; -} - -struct CompileOutput -{ - ShaderCompilerUtil::Output compileOutput; - ShaderInputLayout layout; -}; - -static SlangResult _compile(SlangSession* session, const String& sourcePath, Options::ShaderProgramType shaderType, const ShaderCompilerUtil::Input& input, CompileOutput& output) -{ - List<char> sourceText; - SLANG_RETURN_ON_FAIL(_readSource(sourcePath, sourceText)); - - auto& layout = output.layout; - - // Default the amount of renderTargets based on shader type - switch (shaderType) - { - default: - layout.numRenderTargets = 1; - break; - - case Options::ShaderProgramType::Compute: - layout.numRenderTargets = 0; - break; - } - - // Parse the layout - layout.parse(sourceText.getBuffer()); - layout.updateForTarget(input.target); - - // Setup SourceInfo - ShaderCompileRequest::SourceInfo sourceInfo; - sourceInfo.path = sourcePath.getBuffer(); - sourceInfo.dataBegin = sourceText.getBuffer(); - // Subtract 1 because it's zero terminated - sourceInfo.dataEnd = sourceText.getBuffer() + sourceText.getCount() - 1; - - ShaderCompileRequest compileRequest; - compileRequest.source = sourceInfo; - if (shaderType == Options::ShaderProgramType::Graphics || shaderType == Options::ShaderProgramType::GraphicsCompute) - { - compileRequest.vertexShader.source = sourceInfo; - compileRequest.vertexShader.name = vertexEntryPointName; - compileRequest.fragmentShader.source = sourceInfo; - compileRequest.fragmentShader.name = fragmentEntryPointName; - } - else - { - compileRequest.computeShader.source = sourceInfo; - compileRequest.computeShader.name = computeEntryPointName; - } - compileRequest.globalGenericTypeArguments = layout.globalGenericTypeArguments; - compileRequest.entryPointGenericTypeArguments = layout.entryPointGenericTypeArguments; - compileRequest.globalExistentialTypeArguments = layout.globalExistentialTypeArguments; - compileRequest.entryPointExistentialTypeArguments = layout.entryPointExistentialTypeArguments; - - return ShaderCompilerUtil::compileProgram(session, input, compileRequest, output.compileOutput); -} - -static SlangResult _writeBindings(const ShaderInputLayout& layout, const List<CPUMemoryBinding::Buffer>& buffers, const String& fileName) -{ - FILE * f = fopen(fileName.getBuffer(), "wb"); - if (!f) - { - return SLANG_FAIL; - } - - const auto& entries = layout.entries; - - for (int i = 0; i < entries.getCount(); ++i) - { - const auto& entry = entries[i]; - if (entry.isOutput) - { - const auto& buffer = buffers[i]; - - unsigned int* ptr = (unsigned int*)buffer.m_data; - - const int size = int(entry.bufferData.getCount()); - // Must be the same size or less thatn allocated buffer - SLANG_ASSERT(size * sizeof(unsigned int) <= buffer.m_sizeInBytes); - - for (int i = 0; i < size; ++i) - { - unsigned int v = ptr[i]; - - fprintf(f, "%X\n", v); - } - } - } - fclose(f); - return SLANG_OK; -} - -struct CPUResource: public RefObject -{ - void* getInterface() const { return m_interface; } - void* m_interface; -}; - -template <int COUNT> -struct OneTexture2D: public CPUResource, public CPPPrelude::ITexture2D -{ - void setOne(void* out) - { - float* dst = (float*)out; - for (int i = 0; i < COUNT; ++i) - { - dst[i] = 1.0f; - } - } - - virtual void Load(const CPPPrelude::int3& v, void* out) SLANG_OVERRIDE - { - setOne(out); - } - virtual void Sample(CPPPrelude::SamplerState samplerState, const CPPPrelude::float2& loc, void* out) SLANG_OVERRIDE - { - setOne(out); - } - virtual void SampleLevel(CPPPrelude::SamplerState samplerState, const CPPPrelude::float2& loc, float level, void* out) SLANG_OVERRIDE - { - setOne(out); - } - - OneTexture2D() - { - m_interface = static_cast<CPPPrelude::ITexture2D*>(this); - } -}; - -static CPUResource* _newOneTexture2D(int elemCount) -{ - switch (elemCount) - { - case 1: return new OneTexture2D<1>(); - case 2: return new OneTexture2D<2>(); - case 3: return new OneTexture2D<3>(); - case 4: return new OneTexture2D<4>(); - default: return nullptr; - } -} - -static SlangResult _doCPUCompute(SlangSession* session, const String& sourcePath, Options::ShaderProgramType shaderType, const ShaderCompilerUtil::Input& input) -{ - CompileOutput output; - SLANG_RETURN_ON_FAIL(_compile(session, sourcePath, shaderType, input, output)); - - ComPtr<ISlangSharedLibrary> sharedLibrary; - SLANG_RETURN_ON_FAIL(spGetEntryPointHostCallable(output.compileOutput.request, 0, 0, sharedLibrary.writeRef())); - - // Use reflection to find the entry point name - auto request = output.compileOutput.request; - - struct UniformState; - typedef void(*Func)(CPPPrelude::ComputeVaryingInput* varyingInput, CPPPrelude::UniformEntryPointParams* params, UniformState* uniformState); - - auto reflection = (slang::ShaderReflection*) spGetReflection(request); - - slang::EntryPointReflection* entryPoint = nullptr; - Func func = nullptr; - { - auto entryPointCount = reflection->getEntryPointCount(); - SLANG_ASSERT(entryPointCount == 1); - - entryPoint = reflection->getEntryPointByIndex(0); - - const char* entryPointName = entryPoint->getName(); - func = (Func) sharedLibrary->findFuncByName(entryPointName); - - if (!func) - { - return SLANG_FAIL; - } - } - - CPUMemoryBinding binding; - SLANG_RETURN_ON_FAIL(binding.init(reflection, 0)); - - List<CPUMemoryBinding::Buffer> buffers; - - // Okay we need to find all of the bindings and match up to those in the layout - ShaderInputLayout& layout = output.layout; - - List<RefPtr<CPUResource> > resources; - - { - auto& outStream = StdWriters::getOut(); - auto& entries = layout.entries; - buffers.setCount(entries.getCount()); - - for (int entryIndex = 0; entryIndex < entries.getCount(); ++entryIndex) - { - auto& entry = entries[entryIndex]; - - if (entry.name.getLength() == 0) - { - outStream.print("No 'name' specified for resources in '%s'\n", sourcePath.getBuffer()); - return SLANG_FAIL; - } - - // We will parse the 'name' as may be path to a resource - TokenReader parser(entry.name); - - CPUMemoryBinding::Location location; - - { - Token nameToken = parser.ReadToken(); - if (nameToken.Type != TokenType::Identifier) - { - outStream.print("Invalid input syntax at line %d", int(parser.NextToken().Position.Line)); - return SLANG_FAIL; - } - location = binding.find(nameToken.Content.getBuffer()); - if (location.isInvalid()) - { - outStream.print("Unable to find entry in '%s' for '%s' (for CPU name must be specified) \n", sourcePath.getBuffer(), entry.name.getBuffer()); - return SLANG_FAIL; - } - } - - while (!parser.IsEnd()) - { - Token token = parser.NextToken(0); - - if (token.Type == TokenType::LBracket) - { - parser.ReadToken(); - int index = parser.ReadInt(); - SLANG_ASSERT(index >= 0); - - location = location.toIndex(index); - if (location.isInvalid()) - { - outStream.print("Unable to find entry in '%d' in '%s'\n", index, entry.name.getBuffer()); - return SLANG_FAIL; - } - parser.ReadMatchingToken(TokenType::RBracket); - } - else if (token.Type == TokenType::Dot) - { - parser.ReadToken(); - Token identifierToken = parser.ReadMatchingToken(TokenType::Identifier); - - location = location.toField(identifierToken.Content.getBuffer()); - if (location.isInvalid()) - { - outStream.print("Unable to find field '%s' in '%s'\n", identifierToken.Content.getBuffer(), entry.name.getBuffer()); - return SLANG_FAIL; - } - } - else if (token.Type == TokenType::Comma) - { - // Break out - break; - } - else - { - throw TextFormatException("Invalid input syntax at line " + parser.NextToken().Position.Line); - } - } - - auto& srcEntry = layout.entries[entryIndex]; - - auto typeLayout = location.getTypeLayout(); - const auto kind = typeLayout->getKind(); - switch (kind) - { - case slang::TypeReflection::Kind::Vector: - case slang::TypeReflection::Kind::Matrix: - case slang::TypeReflection::Kind::Array: - case slang::TypeReflection::Kind::Scalar: - case slang::TypeReflection::Kind::Struct: - { - SLANG_RETURN_ON_FAIL(binding.setInplace(location, srcEntry.bufferData.getBuffer(), srcEntry.bufferData.getCount() * sizeof(unsigned int))); - break; - } - default: - break; - case slang::TypeReflection::Kind::ConstantBuffer: - { - SLANG_RETURN_ON_FAIL(binding.setBufferContents(location, srcEntry.bufferData.getBuffer(),srcEntry.bufferData.getCount() * sizeof(unsigned int) )); - break; - } - case slang::TypeReflection::Kind::ParameterBlock: - { - auto elementTypeLayout = typeLayout->getElementTypeLayout(); - SLANG_UNUSED(elementTypeLayout); - break; - } - case slang::TypeReflection::Kind::TextureBuffer: - { - auto elementTypeLayout = typeLayout->getElementTypeLayout(); - SLANG_UNUSED(elementTypeLayout); - break; - } - case slang::TypeReflection::Kind::ShaderStorageBuffer: - { - auto elementTypeLayout = typeLayout->getElementTypeLayout(); - SLANG_UNUSED(elementTypeLayout); - break; - } - case slang::TypeReflection::Kind::GenericTypeParameter: - { - const char* name = typeLayout->getName(); - SLANG_UNUSED(name); - break; - } - case slang::TypeReflection::Kind::Interface: - { - const char* name = typeLayout->getName(); - SLANG_UNUSED(name); - break; - } - case slang::TypeReflection::Kind::Resource: - { - auto type = typeLayout->getType(); - auto shape = type->getResourceShape(); - - //auto access = type->getResourceAccess(); - - switch (shape & SLANG_RESOURCE_BASE_SHAPE_MASK) - { - default: - assert(!"unhandled case"); - break; - case SLANG_TEXTURE_2D: - { - slang::TypeReflection* typeReflection = location.getTypeLayout()->getResourceResultType(); - - int count = 1; - if (typeReflection->getKind() == slang::TypeReflection::Kind::Vector) - { - count = int(typeReflection->getElementCount()); - } - - RefPtr<CPUResource> resource = _newOneTexture2D(count); - resources.add(resource); - - SLANG_RETURN_ON_FAIL(binding.setObject(location, resource->getInterface())); - break; - } - case SLANG_TEXTURE_1D: - case SLANG_TEXTURE_3D: - case SLANG_TEXTURE_CUBE: - case SLANG_TEXTURE_BUFFER: - { - // Just set to null for now - SLANG_RETURN_ON_FAIL(binding.setObject(location, nullptr)); - break; - } - case SLANG_BYTE_ADDRESS_BUFFER: - case SLANG_STRUCTURED_BUFFER: - { - CPUMemoryBinding::Buffer buffer; - SLANG_RETURN_ON_FAIL(binding.setNewBuffer(location, srcEntry.bufferData.getBuffer(), srcEntry.bufferData.getCount() * sizeof(unsigned int), buffer )); - buffers[entryIndex] = buffer; - break; - } - } - if (shape & SLANG_TEXTURE_ARRAY_FLAG) - { - - } - if (shape & SLANG_TEXTURE_MULTISAMPLE_FLAG) - { - - } - - break; - } - } - } - } - - SlangUInt numThreadsPerAxis[3]; - entryPoint->getComputeThreadGroupSize(3, numThreadsPerAxis); - - { - UniformState* uniformState = (UniformState*)binding.m_rootBuffer.m_data; - CPPPrelude::UniformEntryPointParams* params = (CPPPrelude::UniformEntryPointParams*)binding.m_entryPointBuffer.m_data; - - CPPPrelude::ComputeVaryingInput varying; - varying.groupID = {}; - - for (int z = 0; z < int(numThreadsPerAxis[2]); ++z) - { - varying.groupThreadID.z = z; - for (int y = 0; y < int(numThreadsPerAxis[1]); ++y) - { - varying.groupThreadID.y = y; - for (int x = 0; x < int(numThreadsPerAxis[0]); ++x) - { - varying.groupThreadID.x = x; - - func(&varying, params, uniformState); - } - } - } - } - - // Dump everything out that was write (we wrote in place!) - return _writeBindings(layout, buffers, gOptions.outputPath); -} - SlangResult RenderTestApp::initialize(SlangSession* session, Renderer* renderer, Options::ShaderProgramType shaderType, const ShaderCompilerUtil::Input& input) { SLANG_RETURN_ON_FAIL(_initializeShaders(session, renderer, shaderType, input)); @@ -769,10 +335,10 @@ SlangResult RenderTestApp::initialize(SlangSession* session, Renderer* renderer, Result RenderTestApp::_initializeShaders(SlangSession* session, Renderer* renderer, Options::ShaderProgramType shaderType, const ShaderCompilerUtil::Input& input) { - CompileOutput output; - SLANG_RETURN_ON_FAIL(_compile(session, gOptions.sourcePath, shaderType, input, output)); + ShaderCompilerUtil::OutputAndLayout output; + SLANG_RETURN_ON_FAIL(ShaderCompilerUtil::compileWithLayout(session, gOptions.sourcePath, shaderType, input, output)); m_shaderInputLayout = output.layout; - m_shaderProgram = renderer->createProgram(output.compileOutput.desc); + m_shaderProgram = renderer->createProgram(output.output.desc); return m_shaderProgram ? SLANG_OK : SLANG_FAIL; } @@ -1024,8 +590,15 @@ SLANG_TEST_TOOL_API SlangResult innerMain(Slang::StdWriters* stdWriters, SlangSe if (!renderer) { - SLANG_RETURN_ON_FAIL(_doCPUCompute(session, gOptions.sourcePath, gOptions.shaderType, input)); - return SLANG_OK; + ShaderCompilerUtil::OutputAndLayout compilationAndLayout; + SLANG_RETURN_ON_FAIL(ShaderCompilerUtil::compileWithLayout(session, gOptions.sourcePath, gOptions.shaderType, input, compilationAndLayout)); + + CPUComputeUtil::Context context; + SLANG_RETURN_ON_FAIL(CPUComputeUtil::calcBindings(compilationAndLayout, context)); + SLANG_RETURN_ON_FAIL(CPUComputeUtil::execute(compilationAndLayout, context)); + + // Dump everything out that was written + return CPUComputeUtil::writeBindings(compilationAndLayout.layout, context.buffers, gOptions.outputPath); } { |
