diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/gfx/d3d11/render-d3d11.cpp | 101 | ||||
| -rw-r--r-- | tools/gfx/d3d12/render-d3d12.cpp | 74 | ||||
| -rw-r--r-- | tools/gfx/gfx.vcxproj | 3 | ||||
| -rw-r--r-- | tools/gfx/gfx.vcxproj.filters | 9 | ||||
| -rw-r--r-- | tools/gfx/nvapi/nvapi-include.h | 19 | ||||
| -rw-r--r-- | tools/gfx/nvapi/nvapi-util.cpp | 30 | ||||
| -rw-r--r-- | tools/gfx/nvapi/nvapi-util.h | 19 | ||||
| -rw-r--r-- | tools/gfx/open-gl/render-gl.cpp | 7 | ||||
| -rw-r--r-- | tools/gfx/render.h | 7 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 77 | ||||
| -rw-r--r-- | tools/render-test/options.cpp | 73 | ||||
| -rw-r--r-- | tools/render-test/options.h | 6 | ||||
| -rw-r--r-- | tools/render-test/render-test-main.cpp | 152 | ||||
| -rw-r--r-- | tools/render-test/slang-support.cpp | 6 | ||||
| -rw-r--r-- | tools/render-test/slang-support.h | 2 | ||||
| -rw-r--r-- | tools/slang-test/options.cpp | 10 | ||||
| -rw-r--r-- | tools/slang-test/options.h | 3 | ||||
| -rw-r--r-- | tools/slang-test/slang-test-main.cpp | 23 | ||||
| -rw-r--r-- | tools/slang-test/test-context.cpp | 6 | ||||
| -rw-r--r-- | tools/slang-test/test-context.h | 4 |
20 files changed, 479 insertions, 152 deletions
diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp index 4eba4edaf..8eafd24b4 100644 --- a/tools/gfx/d3d11/render-d3d11.cpp +++ b/tools/gfx/d3d11/render-d3d11.cpp @@ -7,6 +7,7 @@ //WORKING: #include "options.h" #include "../render.h" #include "../d3d/d3d-util.h" +#include "../nvapi/nvapi-util.h" #include "../surface.h" @@ -29,6 +30,13 @@ #include <d3d11_2.h> #include <d3dcompiler.h> +#ifdef GFX_NVAPI +// NVAPI integration is desribed here +// https://developer.nvidia.com/unlocking-gpu-intrinsics-hlsl + +# include "../nvapi/nvapi-include.h" +#endif + // We will use the C standard library just for printing error messages. #include <stdio.h> @@ -52,6 +60,7 @@ public: kMaxRTVs = 8, }; + // Renderer implementation virtual SlangResult initialize(const Desc& desc, void* inWindowHandle) override; virtual const List<String>& getFeatures() override { return m_features; } @@ -102,6 +111,17 @@ public: protected: + class ScopeNVAPI + { + public: + ScopeNVAPI() : m_renderer(nullptr) {} + SlangResult init(D3D11Renderer* renderer, Index regIndex); + ~ScopeNVAPI(); + + protected: + D3D11Renderer* m_renderer; + }; + #if 0 struct BindingDetail { @@ -124,6 +144,7 @@ public: }; #endif + enum class D3D11DescriptorSlotType { ConstantBuffer, @@ -391,6 +412,8 @@ public: float m_clearColor[4] = { 0, 0, 0, 0 }; List<String> m_features; + + bool m_nvapi = false; }; Renderer* createD3D11Renderer() @@ -398,6 +421,44 @@ Renderer* createD3D11Renderer() return new D3D11Renderer(); } +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!ScopeNVAPI !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +SlangResult D3D11Renderer::ScopeNVAPI::init(D3D11Renderer* renderer, Index regIndex) +{ + if (!renderer->m_nvapi) + { + // There is nothing to set as nvapi is not set + return SLANG_OK; + } + +#ifdef GFX_NVAPI + NvAPI_Status nvapiStatus = NvAPI_D3D11_SetNvShaderExtnSlot(renderer->m_device, NvU32(regIndex)); + if (nvapiStatus != NVAPI_OK) + { + return SLANG_FAIL; + } +#endif + + // Record the renderer so it can be freed + m_renderer = renderer; + return SLANG_OK; +} + +D3D11Renderer::ScopeNVAPI::~ScopeNVAPI() +{ + // If the m_renderer is not set, it must not have been set up + if (m_renderer) + { +#ifdef GFX_NVAPI + // Disable the slot used + NvAPI_Status nvapiStatus = NvAPI_D3D11_SetNvShaderExtnSlot(m_renderer->m_device, ~0); + SLANG_ASSERT(nvapiStatus == NVAPI_OK); +#endif + } +} + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!D3D11Renderer !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + /* static */HRESULT D3D11Renderer::captureTextureToSurface(ID3D11Device* device, ID3D11DeviceContext* context, ID3D11Texture2D* texture, Surface& surfaceOut) { if (!context) return E_INVALIDARG; @@ -585,6 +646,30 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle) SLANG_ASSERT(m_immediateContext && m_swapChain && m_device); } + // NVAPI + { + const char* features[] = { "nvapi", "atomic-float", "atomic-int64" }; + bool needsNvapi = false; + for (Index i = 0; i < SLANG_COUNT_OF(features); ++i) + { + if (desc.requiredFeatures.indexOf(features[i]) >= 0) + { + needsNvapi = true; + break; + } + } + + if (needsNvapi && SLANG_SUCCEEDED(NVAPIUtil::initialize())) + { + // TODO(JS): We should test for specific features here. + for (Index i = 0; i < SLANG_COUNT_OF(features); ++i) + { + m_features.add(features[i]); + } + m_nvapi = true; + } + } + // TODO: Add support for debugging to help detect leaks: // // ComPtr<ID3D11Debug> gDebug; @@ -1505,7 +1590,12 @@ Result D3D11Renderer::createProgram(const ShaderProgram::Desc& desc, ShaderProgr auto computeKernel = desc.findKernel(StageType::Compute); ComPtr<ID3D11ComputeShader> computeShader; - SLANG_RETURN_ON_FAIL(m_device->CreateComputeShader(computeKernel->codeBegin, computeKernel->getCodeSize(), nullptr, computeShader.writeRef())); + + { + ScopeNVAPI scopeNVAPI; + SLANG_RETURN_ON_FAIL(scopeNVAPI.init(this, 0)); + SLANG_RETURN_ON_FAIL(m_device->CreateComputeShader(computeKernel->codeBegin, computeKernel->getCodeSize(), nullptr, computeShader.writeRef())); + } RefPtr<ShaderProgramImpl> shaderProgram = new ShaderProgramImpl(); shaderProgram->m_computeShader.swap(computeShader); @@ -1521,8 +1611,13 @@ Result D3D11Renderer::createProgram(const ShaderProgram::Desc& desc, ShaderProgr ComPtr<ID3D11VertexShader> vertexShader; ComPtr<ID3D11PixelShader> pixelShader; - SLANG_RETURN_ON_FAIL(m_device->CreateVertexShader(vertexKernel->codeBegin, vertexKernel->getCodeSize(), nullptr, vertexShader.writeRef())); - SLANG_RETURN_ON_FAIL(m_device->CreatePixelShader(fragmentKernel->codeBegin, fragmentKernel->getCodeSize(), nullptr, pixelShader.writeRef())); + { + ScopeNVAPI scopeNVAPI; + SLANG_RETURN_ON_FAIL(scopeNVAPI.init(this, 0)); + + SLANG_RETURN_ON_FAIL(m_device->CreateVertexShader(vertexKernel->codeBegin, vertexKernel->getCodeSize(), nullptr, vertexShader.writeRef())); + SLANG_RETURN_ON_FAIL(m_device->CreatePixelShader(fragmentKernel->codeBegin, fragmentKernel->getCodeSize(), nullptr, pixelShader.writeRef())); + } RefPtr<ShaderProgramImpl> shaderProgram = new ShaderProgramImpl(); shaderProgram->m_vertexShader.swap(vertexShader); diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index ba9bde63a..ca44aa04d 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -23,7 +23,16 @@ #include <dxgi1_4.h> #include <d3d12.h> -#include <d3dcompiler.h> +//#include <d3dcompiler.h> + +#ifndef __ID3D12GraphicsCommandList1_FWD_DEFINED__ +// If can't find a definition of CommandList1, just use an empty definition +struct ID3D12GraphicsCommandList1 {}; +#endif + +#ifdef GFX_NVAPI +# include "../nvapi/nvapi-include.h" +#endif #include "../../slang-com-ptr.h" #include "../flag-combiner.h" @@ -34,6 +43,8 @@ #include "../d3d/d3d-util.h" +#include "../nvapi/nvapi-util.h" + // We will use the C standard library just for printing error messages. #include <stdio.h> @@ -690,6 +701,8 @@ protected: HWND m_hwnd = nullptr; List<String> m_features; + + bool m_nvapi = false; }; Renderer* createD3D12Renderer() @@ -1589,6 +1602,30 @@ Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle) return SLANG_FAIL; } + // NVAPI + { + const char* features[] = { "nvapi", "atomic-float", "atomic-int64" }; + bool needsNvapi = false; + for (Index i = 0; i < SLANG_COUNT_OF(features); ++i) + { + if (desc.requiredFeatures.indexOf(features[i]) >= 0) + { + needsNvapi = true; + break; + } + } + + if (needsNvapi && SLANG_SUCCEEDED(NVAPIUtil::initialize())) + { + // TODO(JS): We should test for specific features here. + for (Index i = 0; i < SLANG_COUNT_OF(features); ++i) + { + m_features.add(features[i]); + } + m_nvapi = true; + } + } + // Set the device m_device = m_deviceInfo.m_device; @@ -3209,7 +3246,7 @@ void D3D12Renderer::DescriptorSetImpl::setRootConstants( // have been a root-constant range for this call to be // valid. // - SLANG_ASSERT(range < m_layout->m_ranges.getCount()); + SLANG_ASSERT(range < UInt(m_layout->m_ranges.getCount())); auto& rangeInfo = m_layout->m_ranges[range]; SLANG_ASSERT(rangeInfo.type == DescriptorSlotType::RootConstant); @@ -3222,7 +3259,7 @@ void D3D12Renderer::DescriptorSetImpl::setRootConstants( SLANG_ASSERT(rootConstantIndex >= 0); SLANG_ASSERT(rootConstantIndex < m_layout->m_rootConstantRanges.getCount()); auto& rootConstantRangeInfo = m_layout->m_rootConstantRanges[rootConstantIndex]; - SLANG_ASSERT(offset + size <= rootConstantRangeInfo.size); + SLANG_ASSERT(offset + size <= UInt(rootConstantRangeInfo.size)); memcpy((char*)m_rootConstantData.getBuffer() + rootConstantRangeInfo.offset + offset, data, size); } @@ -3951,7 +3988,36 @@ Result D3D12Renderer::createComputePipelineState(const ComputePipelineStateDesc& computeDesc.CS = { programImpl->m_computeShader.getBuffer(), SIZE_T(programImpl->m_computeShader.getCount()) }; ComPtr<ID3D12PipelineState> pipelineState; - SLANG_RETURN_ON_FAIL(m_device->CreateComputePipelineState(&computeDesc, IID_PPV_ARGS(pipelineState.writeRef()))); + +#ifdef GFX_NVAPI + if (m_nvapi) + { + // Also fill the extension structure. + // Use the same UAV slot index and register space that are declared in the shader. + + // For simplicities sake we just use u0 + NVAPI_D3D12_PSO_SET_SHADER_EXTENSION_SLOT_DESC extensionDesc; + extensionDesc.baseVersion = NV_PSO_EXTENSION_DESC_VER; + extensionDesc.version = NV_SET_SHADER_EXTENSION_SLOT_DESC_VER; + extensionDesc.uavSlot = 0; + extensionDesc.registerSpace = 0; + + // Put the pointer to the extension into an array - there can be multiple extensions enabled at once. + const NVAPI_D3D12_PSO_EXTENSION_DESC* extensions[] = { &extensionDesc }; + + // Now create the PSO. + const NvAPI_Status nvapiStatus = NvAPI_D3D12_CreateComputePipelineState(m_device, &computeDesc, SLANG_COUNT_OF(extensions), extensions, pipelineState.writeRef()); + + if (nvapiStatus != NVAPI_OK) + { + return SLANG_FAIL; + } + } + else +#endif + { + SLANG_RETURN_ON_FAIL(m_device->CreateComputePipelineState(&computeDesc, IID_PPV_ARGS(pipelineState.writeRef()))); + } RefPtr<PipelineStateImpl> pipelineStateImpl = new PipelineStateImpl(); pipelineStateImpl->m_pipelineType = PipelineType::Compute; diff --git a/tools/gfx/gfx.vcxproj b/tools/gfx/gfx.vcxproj index d4b1885a8..327f6d629 100644 --- a/tools/gfx/gfx.vcxproj +++ b/tools/gfx/gfx.vcxproj @@ -180,6 +180,8 @@ <ClInclude Include="flag-combiner.h" /> <ClInclude Include="gui.h" /> <ClInclude Include="model.h" /> + <ClInclude Include="nvapi\nvapi-include.h" /> + <ClInclude Include="nvapi\nvapi-util.h" /> <ClInclude Include="open-gl\render-gl.h" /> <ClInclude Include="render.h" /> <ClInclude Include="surface.h" /> @@ -202,6 +204,7 @@ <ClCompile Include="flag-combiner.cpp" /> <ClCompile Include="gui.cpp" /> <ClCompile Include="model.cpp" /> + <ClCompile Include="nvapi\nvapi-util.cpp" /> <ClCompile Include="open-gl\render-gl.cpp" /> <ClCompile Include="render.cpp" /> <ClCompile Include="surface.cpp" /> diff --git a/tools/gfx/gfx.vcxproj.filters b/tools/gfx/gfx.vcxproj.filters index 1c27e4f24..f5fba2295 100644 --- a/tools/gfx/gfx.vcxproj.filters +++ b/tools/gfx/gfx.vcxproj.filters @@ -36,6 +36,12 @@ <ClInclude Include="model.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="nvapi\nvapi-include.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="nvapi\nvapi-util.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="open-gl\render-gl.h"> <Filter>Header Files</Filter> </ClInclude> @@ -98,6 +104,9 @@ <ClCompile Include="model.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="nvapi\nvapi-util.cpp"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="open-gl\render-gl.cpp"> <Filter>Source Files</Filter> </ClCompile> diff --git a/tools/gfx/nvapi/nvapi-include.h b/tools/gfx/nvapi/nvapi-include.h new file mode 100644 index 000000000..e3674af95 --- /dev/null +++ b/tools/gfx/nvapi/nvapi-include.h @@ -0,0 +1,19 @@ +// nvapi-include.h +#pragma once + +// A helper that makes the NVAPI available across targets + +#ifdef GFX_NVAPI +// On windows if we include NVAPI, we must include windows.h first + +# ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <Windows.h> +# undef WIN32_LEAN_AND_MEAN +# undef NOMINMAX +# endif + +# include <nvapi.h> +#endif + diff --git a/tools/gfx/nvapi/nvapi-util.cpp b/tools/gfx/nvapi/nvapi-util.cpp new file mode 100644 index 000000000..63bcc65fc --- /dev/null +++ b/tools/gfx/nvapi/nvapi-util.cpp @@ -0,0 +1,30 @@ +#include "nvapi-util.h" + +#include "nvapi-include.h" + +namespace gfx { + +static SlangResult g_initStatus = SLANG_E_UNINITIALIZED; + +/* static */SlangResult NVAPIUtil::initialize() +{ +#ifdef GFX_NVAPI + if (g_initStatus == SLANG_E_UNINITIALIZED) + { + NvAPI_Status ret = NVAPI_OK; + ret = NvAPI_Initialize(); + g_initStatus = (ret == NVAPI_OK) ? SLANG_OK : SLANG_E_NOT_AVAILABLE; + } +#else + g_initStatus = SLANG_E_NOT_AVAILABLE; +#endif + + return g_initStatus; +} + +/* static */bool NVAPIUtil::isAvailable() +{ + return SLANG_SUCCEEDED(g_initStatus); +} + +} // gfx diff --git a/tools/gfx/nvapi/nvapi-util.h b/tools/gfx/nvapi/nvapi-util.h new file mode 100644 index 000000000..704f4ede4 --- /dev/null +++ b/tools/gfx/nvapi/nvapi-util.h @@ -0,0 +1,19 @@ +// nvapi-util.h +#pragma once + +#include "../../slang-com-helper.h" +#include "../../slang-com-ptr.h" + +namespace gfx { + +struct NVAPIUtil +{ + /// Set up NVAPI for use. Must be called before any other function is used. + static SlangResult initialize(); + /// True if the NVAPI is available, can be called even if initialize fails. + /// If initialize has not been called will return false + static bool isAvailable(); +}; + + +} // gfx diff --git a/tools/gfx/open-gl/render-gl.cpp b/tools/gfx/open-gl/render-gl.cpp index ee3977a74..5f16f07bc 100644 --- a/tools/gfx/open-gl/render-gl.cpp +++ b/tools/gfx/open-gl/render-gl.cpp @@ -1,6 +1,8 @@ // render-gl.cpp #include "render-gl.h" +#include "../nvapi/nvapi-util.h" + //WORKING:#include "options.h" #include "../render.h" @@ -715,6 +717,11 @@ SlangResult GLRenderer::initialize(const Desc& desc, void* inWindowHandle) } } + if (m_desc.requiredFeatures.indexOf("nvapi") >= 0 && SLANG_SUCCEEDED(NVAPIUtil::initialize())) + { + m_features.add("nvapi"); + } + auto extensions = glGetString(GL_EXTENSIONS); // Load each of our extension functions by name diff --git a/tools/gfx/render.h b/tools/gfx/render.h index 051b19742..12ef1a9e9 100644 --- a/tools/gfx/render.h +++ b/tools/gfx/render.h @@ -800,9 +800,10 @@ public: struct Desc { - int width; ///< Width in pixels - int height; ///< height in pixels - Slang::String adapter; ///< Name to identify the adapter to use + int width; ///< Width in pixels + int height; ///< height in pixels + Slang::String adapter; ///< Name to identify the adapter to use + Slang::List<Slang::String> requiredFeatures; ///< The features enabled on this renderer }; virtual SlangResult initialize(const Desc& desc, void* inWindowHandle) = 0; diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index b9cc82469..28567a3b8 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -1025,31 +1025,40 @@ SlangResult VKRenderer::initialize(const Desc& desc, void* inWindowHandle) const uint32_t majorVersion = VK_VERSION_MAJOR(basicProps.apiVersion); const uint32_t minorVersion = VK_VERSION_MINOR(basicProps.apiVersion); - // Float16 features // Need in this scope because it will be linked into the device creation (if it is available) + + // Float16 features VkPhysicalDeviceFloat16Int8FeaturesKHR float16Features = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR }; + // AtomicInt64 features + VkPhysicalDeviceShaderAtomicInt64FeaturesKHR atomicInt64Features = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR }; + // Atomic Float features + VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomicFloatFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT }; // API version check, can't use vkGetPhysicalDeviceProperties2 yet since this device might not support it if (VK_MAKE_VERSION(majorVersion, minorVersion, 0) >= VK_API_VERSION_1_1 && m_api.vkGetPhysicalDeviceProperties2 && m_api.vkGetPhysicalDeviceFeatures2) { - VkPhysicalDeviceProperties2 physicalDeviceProps2; - - physicalDeviceProps2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - physicalDeviceProps2.pNext = nullptr; - physicalDeviceProps2.properties = {}; - - m_api.vkGetPhysicalDeviceProperties2(m_api.m_physicalDevice, &physicalDeviceProps2); // Get device features VkPhysicalDeviceFeatures2 deviceFeatures2 = {}; deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - // Link together for lookup + // Float16 float16Features.pNext = deviceFeatures2.pNext; deviceFeatures2.pNext = &float16Features; + // Atomic64 + atomicInt64Features.pNext = deviceFeatures2.pNext; + deviceFeatures2.pNext = &atomicInt64Features; + + // Atomic Float + // To detect atomic float we need + // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkPhysicalDeviceShaderAtomicFloatFeaturesEXT.html + + atomicFloatFeatures.pNext = deviceFeatures2.pNext; + deviceFeatures2.pNext = &atomicFloatFeatures; + m_api.vkGetPhysicalDeviceFeatures2(m_api.m_physicalDevice, &deviceFeatures2); // If we have float16 features then enable @@ -1064,7 +1073,27 @@ SlangResult VKRenderer::initialize(const Desc& desc, void* inWindowHandle) // We have half support m_features.add("half"); - } + } + + if (atomicInt64Features.shaderBufferInt64Atomics) + { + // Link into the creation features + atomicInt64Features.pNext = (void*)deviceCreateInfo.pNext; + deviceCreateInfo.pNext = &atomicInt64Features; + + deviceExtensions.add(VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME); + m_features.add("atomic-int64"); + } + + if (atomicFloatFeatures.shaderBufferFloat32AtomicAdd) + { + // Link into the creation features + atomicFloatFeatures.pNext = (void*)deviceCreateInfo.pNext; + deviceCreateInfo.pNext = &atomicFloatFeatures; + + deviceExtensions.add(VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME); + m_features.add("atomic-float"); + } } int queueFamilyIndex = m_api.findQueue(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT); @@ -2345,8 +2374,7 @@ Result VKRenderer::createDescriptorSetLayout(const DescriptorSetLayout::Desc& de RefPtr<DescriptorSetLayoutImpl> descriptorSetLayoutImpl = new DescriptorSetLayoutImpl(m_api); Slang::List<VkDescriptorSetLayoutBinding> dstBindings; - - uint32_t descriptorCountForTypes[VK_DESCRIPTOR_TYPE_RANGE_SIZE] = { 0, }; + Slang::List<uint32_t> descriptorCountForTypes; UInt rangeCount = desc.slotRangeCount; for(UInt rr = 0; rr < rangeCount; ++rr) @@ -2378,7 +2406,7 @@ Result VKRenderer::createDescriptorSetLayout(const DescriptorSetLayout::Desc& de auto rootConstantRangeIndex = descriptorSetLayoutImpl->m_rootConstantRanges.getCount(); descriptorSetLayoutImpl->m_rootConstantRanges.add(rootConstantRangeInfo); - // We will also add a `RangeInfo` to reprsent this + // We will also add a `RangeInfo` to represent this // range, even though it doesn't map to a VK-level // descriptor range. // @@ -2413,6 +2441,11 @@ Result VKRenderer::createDescriptorSetLayout(const DescriptorSetLayout::Desc& de dstBinding.stageFlags = VK_SHADER_STAGE_ALL; dstBinding.pImmutableSamplers = nullptr; + if (descriptorCountForTypes.getCount() <= dstDescriptorType) + { + descriptorCountForTypes.setCount(dstDescriptorType + 1); + } + descriptorCountForTypes[dstDescriptorType] += uint32_t(srcRange.count); dstBindings.add(dstBinding); @@ -2443,23 +2476,23 @@ Result VKRenderer::createDescriptorSetLayout(const DescriptorSetLayout::Desc& de // Create a pool while we are at it, to allocate descriptor sets of this type. - VkDescriptorPoolSize poolSizes[VK_DESCRIPTOR_TYPE_RANGE_SIZE]; - uint32_t poolSizeCount = 0; - for (int ii = 0; ii < SLANG_COUNT_OF(descriptorCountForTypes); ++ii) + List<VkDescriptorPoolSize> poolSizes; + for (Index ii = 0; ii < descriptorCountForTypes.getCount(); ++ii) { auto descriptorCount = descriptorCountForTypes[ii]; if (descriptorCount > 0) { - poolSizes[poolSizeCount].type = VkDescriptorType(ii); - poolSizes[poolSizeCount].descriptorCount = descriptorCount; - poolSizeCount++; + VkDescriptorPoolSize poolSize; + poolSize.type = VkDescriptorType(ii); + poolSize.descriptorCount = descriptorCount; + poolSizes.add(poolSize); } } VkDescriptorPoolCreateInfo descriptorPoolInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; descriptorPoolInfo.maxSets = 128; // TODO: actually pick a size. - descriptorPoolInfo.poolSizeCount = poolSizeCount; - descriptorPoolInfo.pPoolSizes = &poolSizes[0]; + descriptorPoolInfo.poolSizeCount = uint32_t(poolSizes.getCount()); + descriptorPoolInfo.pPoolSizes = poolSizes.getBuffer(); VkDescriptorPool descriptorPool = VK_NULL_HANDLE; SLANG_VK_CHECK(m_api.vkCreateDescriptorPool(m_device, &descriptorPoolInfo, nullptr, &descriptorPool)); @@ -2712,7 +2745,7 @@ void VKRenderer::DescriptorSetImpl::setRootConstants( SLANG_ASSERT(rootConstantIndex >= 0); SLANG_ASSERT(rootConstantIndex < m_layout->m_rootConstantRanges.getCount()); auto& rootConstantRangeInfo = m_layout->m_rootConstantRanges[rootConstantIndex]; - SLANG_ASSERT(offset + size <= rootConstantRangeInfo.size); + SLANG_ASSERT(offset + size <= UInt(rootConstantRangeInfo.size)); memcpy(m_rootConstantData.getBuffer() + rootConstantRangeInfo.offset + offset, data, size); } diff --git a/tools/render-test/options.cpp b/tools/render-test/options.cpp index c2afe78ac..fd4b75ed1 100644 --- a/tools/render-test/options.cpp +++ b/tools/render-test/options.cpp @@ -18,10 +18,6 @@ namespace renderer_test { using namespace Slang; -static const Options gDefaultOptions = Options(); - -Options gOptions; - static gfx::RendererType _toRenderType(Slang::RenderApiType apiType) { using namespace Slang; @@ -37,23 +33,22 @@ static gfx::RendererType _toRenderType(Slang::RenderApiType apiType) } } -static SlangResult _setRendererType(RendererType type, const char* arg, Slang::WriterHelper stdError) +static SlangResult _setRendererType(RendererType type, const char* arg, Slang::WriterHelper stdError, Options& ioOptions) { - if (gOptions.rendererType != RendererType::Unknown) + if (ioOptions.rendererType != RendererType::Unknown) { stdError.print("Already has renderer option set. Found '%s'\n", arg); return SLANG_FAIL; } - gOptions.rendererType = type; + ioOptions.rendererType = type; return SLANG_OK; } -SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper stdError) +/* static */SlangResult Options::parse(int argc, const char*const* argv, Slang::WriterHelper stdError, Options& outOptions) { using namespace Slang; - // Reset the options - gOptions = gDefaultOptions; + outOptions = Options(); List<const char*> positionalArgs; @@ -68,7 +63,7 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s // first argument is the application name if( argCursor != argEnd ) { - gOptions.appName = *argCursor++; + outOptions.appName = *argCursor++; } // now iterate over arguments to collect options @@ -96,7 +91,7 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s stdError.print("expected argument for '%s' option\n", arg); return SLANG_FAIL; } - gOptions.outputPath = *argCursor++; + outOptions.outputPath = *argCursor++; } else if (strcmp(arg, "-profile") == 0) { @@ -105,7 +100,7 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s stdError.print("expected argument for '%s' option\n", arg); return SLANG_FAIL; } - gOptions.profileName = *argCursor++; + outOptions.profileName = *argCursor++; } else if (strcmp(arg, "-render-features") == 0 || strcmp(arg, "-render-feature") == 0) { @@ -121,7 +116,7 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s for (const auto& value : values) { - gOptions.renderFeatures.add(value); + outOptions.renderFeatures.add(value); } } else if( strcmp(arg, "-xslang") == 0 ) @@ -133,36 +128,36 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s stdError.print("expected argument for '%s' option\n", arg); return SLANG_FAIL; } - if( gOptions.slangArgCount == Options::kMaxSlangArgs ) + if( outOptions.slangArgCount == Options::kMaxSlangArgs ) { stdError.print("maximum number of '%s' options exceeded (%d)\n", arg, Options::kMaxSlangArgs); return SLANG_FAIL; } - gOptions.slangArgs[gOptions.slangArgCount++] = *argCursor++; + outOptions.slangArgs[outOptions.slangArgCount++] = *argCursor++; } else if (strcmp(arg, "-compute") == 0) { - gOptions.shaderType = ShaderProgramType::Compute; + outOptions.shaderType = ShaderProgramType::Compute; } else if (strcmp(arg, "-graphics") == 0) { - gOptions.shaderType = ShaderProgramType::Graphics; + outOptions.shaderType = ShaderProgramType::Graphics; } else if (strcmp(arg, "-gcompute") == 0) { - gOptions.shaderType = ShaderProgramType::GraphicsCompute; + outOptions.shaderType = ShaderProgramType::GraphicsCompute; } else if (strcmp(arg, "-rt") == 0) { - gOptions.shaderType = ShaderProgramType::RayTracing; + outOptions.shaderType = ShaderProgramType::RayTracing; } else if( strcmp(arg, "-use-dxil") == 0 ) { - gOptions.useDXIL = true; + outOptions.useDXIL = true; } else if (strcmp(arg, "-only-startup") == 0) { - gOptions.onlyStartup = true; + outOptions.onlyStartup = true; } else if (strcmp(arg, "-compile-arg") == 0) { @@ -175,11 +170,11 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s CommandLine::Arg arg; arg.type = CommandLine::ArgType::Escaped; arg.value = *argCursor++; - gOptions.compileArgs.add(arg); + outOptions.compileArgs.add(arg); } else if (strcmp(arg, "-performance-profile") == 0) { - gOptions.performanceProfile = true; + outOptions.performanceProfile = true; } else if (strcmp(arg, "-adapter") == 0) { @@ -189,11 +184,11 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s return SLANG_FAIL; } - gOptions.adapter = *argCursor++; + outOptions.adapter = *argCursor++; } else if (strcmp(arg, "-output-using-type") == 0) { - gOptions.outputUsingType = true; + outOptions.outputUsingType = true; } else if (strcmp(arg, "-compute-dispatch") == 0) { @@ -220,7 +215,7 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s stdError.print("error: expected 3 comma positive integers for compute dispatch size for '%s'\n", arg); return SLANG_FAIL; } - gOptions.computeDispatchSize[i] = v; + outOptions.computeDispatchSize[i] = v; } } else if (strcmp(arg, "-source-language") == 0) @@ -239,11 +234,21 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s return SLANG_FAIL; } - gOptions.sourceLanguage = sourceLanguage; + outOptions.sourceLanguage = sourceLanguage; } else if( strcmp(arg, "-no-default-entry-point") == 0 ) { - gOptions.dontAddDefaultEntryPoints = true; + outOptions.dontAddDefaultEntryPoints = true; + } + else if (strcmp(arg, "-nvapi-register") == 0) + { + if (argCursor == argEnd) + { + stdError.print("error: expecting a register name for '%s'\n", arg); + return SLANG_FAIL; + } + + outOptions.nvapiRegister = (*argCursor++); } else { @@ -257,7 +262,7 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s if (rendererType != RendererType::Unknown) { - gOptions.rendererType = rendererType; + outOptions.rendererType = rendererType; continue; } @@ -265,8 +270,8 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s RendererType languageRenderType = _toRenderType(RenderApiUtil::findImplicitLanguageRenderApiType(argName)); if (languageRenderType != RendererType::Unknown) { - gOptions.targetLanguageRendererType = languageRenderType; - gOptions.inputLanguageID = (argName == "hlsl" || argName == "glsl" || argName == "cpp" || argName == "cxx" || argName == "c") ? InputLanguageID::Native : InputLanguageID::Slang; + outOptions.targetLanguageRendererType = languageRenderType; + outOptions.inputLanguageID = (argName == "hlsl" || argName == "glsl" || argName == "cpp" || argName == "cxx" || argName == "c") ? InputLanguageID::Native : InputLanguageID::Slang; continue; } } @@ -277,12 +282,12 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s } // If a render option isn't set use defaultRenderType - gOptions.rendererType = (gOptions.rendererType == RendererType::Unknown) ? gOptions.targetLanguageRendererType : gOptions.rendererType; + outOptions.rendererType = (outOptions.rendererType == RendererType::Unknown) ? outOptions.targetLanguageRendererType : outOptions.rendererType; // first positional argument is source shader path if(positionalArgs.getCount()) { - gOptions.sourcePath = positionalArgs[0]; + outOptions.sourcePath = positionalArgs[0]; positionalArgs.removeAt(0); } diff --git a/tools/render-test/options.h b/tools/render-test/options.h index f2f0a8ab6..d311568d4 100644 --- a/tools/render-test/options.h +++ b/tools/render-test/options.h @@ -74,10 +74,10 @@ struct Options Slang::String adapter; ///< The adapter to use either name or index uint32_t computeDispatchSize[3] = { 1, 1, 1 }; -}; -extern Options gOptions; + Slang::String nvapiRegister; ///< The nvapiRegister to use. -SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper stdError); + static SlangResult parse(int argc, const char*const* argv, Slang::WriterHelper stdError, Options& outOptions); +}; } // renderer_test diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp index 7efea40f9..e7356901d 100644 --- a/tools/render-test/render-test-main.cpp +++ b/tools/render-test/render-test-main.cpp @@ -212,7 +212,7 @@ SlangResult RenderTestApp::initialize(SlangSession* session, Renderer* renderer, Result RenderTestApp::_initializeShaders(SlangSession* session, Renderer* renderer, Options::ShaderProgramType shaderType, const ShaderCompilerUtil::Input& input) { - SLANG_RETURN_ON_FAIL(ShaderCompilerUtil::compileWithLayout(session, gOptions, input, m_compilationOutput)); + SLANG_RETURN_ON_FAIL(ShaderCompilerUtil::compileWithLayout(session, m_options, input, m_compilationOutput)); m_shaderInputLayout = m_compilationOutput.layout; m_shaderProgram = renderer->createProgram(m_compilationOutput.output.desc); return m_shaderProgram ? SLANG_OK : SLANG_FAIL; @@ -368,9 +368,9 @@ Result RenderTestApp::update(Window* window) _outputProfileTime(m_startTicks, endTicks); } - if (gOptions.outputPath) + if (m_options.outputPath) { - if (gOptions.shaderType == Options::ShaderProgramType::Compute || gOptions.shaderType == Options::ShaderProgramType::GraphicsCompute) + if (m_options.shaderType == Options::ShaderProgramType::Compute || m_options.shaderType == Options::ShaderProgramType::GraphicsCompute) { auto request = m_compilationOutput.output.request; auto slangReflection = (slang::ShaderReflection*) spGetReflection(request); @@ -379,13 +379,13 @@ Result RenderTestApp::update(Window* window) GPULikeBindRoot bindRoot; bindRoot.init(&bindSet, slangReflection, 0); - BindRoot* outputBindRoot = gOptions.outputUsingType ? &bindRoot : nullptr; + BindRoot* outputBindRoot = m_options.outputUsingType ? &bindRoot : nullptr; - SLANG_RETURN_ON_FAIL(writeBindingOutput(outputBindRoot, gOptions.outputPath)); + SLANG_RETURN_ON_FAIL(writeBindingOutput(outputBindRoot, m_options.outputPath)); } else { - SlangResult res = writeScreen(gOptions.outputPath); + SlangResult res = writeScreen(m_options.outputPath); if (SLANG_FAILED(res)) { fprintf(stderr, "ERROR: failed to write screen capture to file\n"); @@ -403,6 +403,33 @@ Result RenderTestApp::update(Window* window) } +static SlangResult _setSessionPrelude(const Options& options, const char* exePath, SlangSession* session) +{ + // Let's see if we need to set up special prelude for HLSL + if (options.nvapiRegister.getLength()) + { + String rootPath; + SLANG_RETURN_ON_FAIL(TestToolUtil::getRootPath(exePath, rootPath)); + + String includePath; + SLANG_RETURN_ON_FAIL(TestToolUtil::getIncludePath(rootPath, "external/nvapi/nvHLSLExtns.h", includePath)); + + StringBuilder buf; + // We have to choose a slot that NVAPI will use. + buf << "#define NV_SHADER_EXTN_SLOT " << options.nvapiRegister << "\n"; + + // Include the NVAPI header + buf << "#include \"" << includePath << "\"\n\n"; + + session->setLanguagePrelude(SLANG_SOURCE_LANGUAGE_HLSL, buf.getBuffer()); + } + else + { + session->setLanguagePrelude(SLANG_SOURCE_LANGUAGE_HLSL, ""); + } + + return SLANG_OK; +} } // namespace renderer_test @@ -413,8 +440,10 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi StdWriters::setSingleton(stdWriters); + Options options; + // Parse command-line options - SLANG_RETURN_ON_FAIL(parseOptions(argcIn, argvIn, StdWriters::getError())); + SLANG_RETURN_ON_FAIL(Options::parse(argcIn, argvIn, StdWriters::getError(), options)); // Declare window pointer before renderer, such that window is released after renderer RefPtr<renderer_test::Window> window; @@ -423,13 +452,13 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi input.profile = ""; input.target = SLANG_TARGET_NONE; - input.args = &gOptions.slangArgs[0]; - input.argCount = gOptions.slangArgCount; + input.args = &options.slangArgs[0]; + input.argCount = options.slangArgCount; SlangSourceLanguage nativeLanguage = SLANG_SOURCE_LANGUAGE_UNKNOWN; SlangPassThrough slangPassThrough = SLANG_PASS_THROUGH_NONE; char const* profileName = ""; - switch (gOptions.rendererType) + switch (options.rendererType) { case RendererType::DirectX11: input.target = SLANG_DXBC; @@ -445,7 +474,7 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi nativeLanguage = SLANG_SOURCE_LANGUAGE_HLSL; slangPassThrough = SLANG_PASS_THROUGH_FXC; - if( gOptions.useDXIL ) + if( options.useDXIL ) { input.target = SLANG_DXIL; input.profile = "sm_6_0"; @@ -484,7 +513,7 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi return SLANG_FAIL; } - switch (gOptions.inputLanguageID) + switch (options.inputLanguageID) { case Options::InputLanguageID::Slang: input.sourceLanguage = SLANG_SOURCE_LANGUAGE_SLANG; @@ -500,7 +529,7 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi break; } - switch( gOptions.shaderType ) + switch( options.shaderType ) { case Options::ShaderProgramType::Graphics: case Options::ShaderProgramType::GraphicsCompute: @@ -519,9 +548,9 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi break; } - if (gOptions.sourceLanguage != SLANG_SOURCE_LANGUAGE_UNKNOWN) + if (options.sourceLanguage != SLANG_SOURCE_LANGUAGE_UNKNOWN) { - input.sourceLanguage = gOptions.sourceLanguage; + input.sourceLanguage = options.sourceLanguage; if (input.sourceLanguage == SLANG_SOURCE_LANGUAGE_C || input.sourceLanguage == SLANG_SOURCE_LANGUAGE_CPP) { @@ -530,18 +559,18 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi } // Use the profile name set on options if set - input.profile = gOptions.profileName ? gOptions.profileName : input.profile; + input.profile = options.profileName ? options.profileName : input.profile; StringBuilder rendererName; - rendererName << "[" << RendererUtil::toText(gOptions.rendererType) << "] "; - if (gOptions.adapter.getLength()) + rendererName << "[" << RendererUtil::toText(options.rendererType) << "] "; + if (options.adapter.getLength()) { - rendererName << "'" << gOptions.adapter << "'"; + rendererName << "'" << options.adapter << "'"; } - if (gOptions.onlyStartup) + if (options.onlyStartup) { - switch (gOptions.rendererType) + switch (options.rendererType) { case RendererType::CUDA: { @@ -560,11 +589,27 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi } } + // Let's see if we need to set up special prelude for HLSL + if (options.nvapiRegister.getLength()) + { + // We require nvapi to be available on the device + if (options.renderFeatures.indexOf("nvapi") < 0) + { + options.renderFeatures.add("nvapi"); + } + } + + // If can't set up a necessary prelude make not available (which will lead to the test being ignored) + if (SLANG_FAILED(_setSessionPrelude(options, argvIn[0], session))) + { + return SLANG_E_NOT_AVAILABLE; + } + // If it's CPU testing we don't need a window or a renderer - if (gOptions.rendererType == RendererType::CPU) + if (options.rendererType == RendererType::CPU) { // Check we have all the required features - for (const auto& renderFeature : gOptions.renderFeatures) + for (const auto& renderFeature : options.renderFeatures) { if (!CPUComputeUtil::hasFeature(renderFeature.getUnownedSlice())) { @@ -573,7 +618,7 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi } ShaderCompilerUtil::OutputAndLayout compilationAndLayout; - SLANG_RETURN_ON_FAIL(ShaderCompilerUtil::compileWithLayout(session, gOptions, input, compilationAndLayout)); + SLANG_RETURN_ON_FAIL(ShaderCompilerUtil::compileWithLayout(session, options, input, compilationAndLayout)); { // Get the shared library -> it contains the executable code, we need to keep around if we recompile @@ -586,7 +631,7 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi // of the test implementer to *ensure* that the straight C++ code has the same layout as the slang C++ backend. // // If we are running c/c++ we still need binding information, so compile again as slang source - if (gOptions.sourceLanguage == SLANG_SOURCE_LANGUAGE_C || input.sourceLanguage == SLANG_SOURCE_LANGUAGE_CPP) + if (options.sourceLanguage == SLANG_SOURCE_LANGUAGE_C || input.sourceLanguage == SLANG_SOURCE_LANGUAGE_CPP) { ShaderCompilerUtil::Input slangInput = input; slangInput.sourceLanguage = SLANG_SOURCE_LANGUAGE_SLANG; @@ -594,7 +639,7 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi // We just want CPP, so we get suitable reflection slangInput.target = SLANG_CPP_SOURCE; - SLANG_RETURN_ON_FAIL(ShaderCompilerUtil::compileWithLayout(session, gOptions, slangInput, compilationAndLayout)); + SLANG_RETURN_ON_FAIL(ShaderCompilerUtil::compileWithLayout(session, options, slangInput, compilationAndLayout)); } // calculate binding @@ -603,39 +648,39 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi // Get the execution info from the lib CPUComputeUtil::ExecuteInfo info; - SLANG_RETURN_ON_FAIL(CPUComputeUtil::calcExecuteInfo(CPUComputeUtil::ExecuteStyle::GroupRange, sharedLibrary, gOptions.computeDispatchSize, compilationAndLayout, context, info)); + SLANG_RETURN_ON_FAIL(CPUComputeUtil::calcExecuteInfo(CPUComputeUtil::ExecuteStyle::GroupRange, sharedLibrary, options.computeDispatchSize, compilationAndLayout, context, info)); const uint64_t startTicks = ProcessUtil::getClockTick(); SLANG_RETURN_ON_FAIL(CPUComputeUtil::execute(info)); - if (gOptions.performanceProfile) + if (options.performanceProfile) { const uint64_t endTicks = ProcessUtil::getClockTick(); _outputProfileTime(startTicks, endTicks); } - if (gOptions.outputPath) + if (options.outputPath) { - BindRoot* outputBindRoot = gOptions.outputUsingType ? &context.m_bindRoot : nullptr; + BindRoot* outputBindRoot = options.outputUsingType ? &context.m_bindRoot : nullptr; // Dump everything out that was written - SLANG_RETURN_ON_FAIL(ShaderInputLayout::writeBindings(outputBindRoot, compilationAndLayout.layout, context.m_buffers, gOptions.outputPath)); + SLANG_RETURN_ON_FAIL(ShaderInputLayout::writeBindings(outputBindRoot, compilationAndLayout.layout, context.m_buffers, options.outputPath)); // Check all execution styles produce the same result - SLANG_RETURN_ON_FAIL(CPUComputeUtil::checkStyleConsistency(sharedLibrary, gOptions.computeDispatchSize, compilationAndLayout)); + SLANG_RETURN_ON_FAIL(CPUComputeUtil::checkStyleConsistency(sharedLibrary, options.computeDispatchSize, compilationAndLayout)); } } return SLANG_OK; } - if (gOptions.rendererType == RendererType::CUDA) + if (options.rendererType == RendererType::CUDA) { #if RENDER_TEST_CUDA // Check we have all the required features - for (const auto& renderFeature : gOptions.renderFeatures) + for (const auto& renderFeature : options.renderFeatures) { if (!CUDAComputeUtil::hasFeature(renderFeature.getUnownedSlice())) { @@ -644,25 +689,25 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi } ShaderCompilerUtil::OutputAndLayout compilationAndLayout; - SLANG_RETURN_ON_FAIL(ShaderCompilerUtil::compileWithLayout(session, gOptions, input, compilationAndLayout)); + SLANG_RETURN_ON_FAIL(ShaderCompilerUtil::compileWithLayout(session, options, input, compilationAndLayout)); const uint64_t startTicks = ProcessUtil::getClockTick(); CUDAComputeUtil::Context context; - SLANG_RETURN_ON_FAIL(CUDAComputeUtil::execute(compilationAndLayout, gOptions.computeDispatchSize, context)); + SLANG_RETURN_ON_FAIL(CUDAComputeUtil::execute(compilationAndLayout, options.computeDispatchSize, context)); - if (gOptions.performanceProfile) + if (options.performanceProfile) { const uint64_t endTicks = ProcessUtil::getClockTick(); _outputProfileTime(startTicks, endTicks); } - if (gOptions.outputPath) + if (options.outputPath) { - BindRoot* outputBindRoot = gOptions.outputUsingType ? &context.m_bindRoot : nullptr; + BindRoot* outputBindRoot = options.outputUsingType ? &context.m_bindRoot : nullptr; // Dump everything out that was written - SLANG_RETURN_ON_FAIL(ShaderInputLayout::writeBindings(outputBindRoot, compilationAndLayout.layout, context.m_buffers, gOptions.outputPath)); + SLANG_RETURN_ON_FAIL(ShaderInputLayout::writeBindings(outputBindRoot, compilationAndLayout.layout, context.m_buffers, options.outputPath)); } return SLANG_OK; @@ -671,9 +716,19 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi #endif } + if (options.nvapiRegister.getLength()) + { + // We require nvapi to be available on the device + if (options.renderFeatures.indexOf("nvapi") < 0) + { + options.renderFeatures.add("nvapi"); + } + } + + Slang::RefPtr<Renderer> renderer; { - RendererUtil::CreateFunc createFunc = RendererUtil::getCreateFunc(gOptions.rendererType); + RendererUtil::CreateFunc createFunc = RendererUtil::getCreateFunc(options.rendererType); if (createFunc) { renderer = createFunc(); @@ -681,7 +736,7 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi if (!renderer) { - if (!gOptions.onlyStartup) + if (!options.onlyStartup) { fprintf(stderr, "Unable to create renderer %s\n", rendererName.getBuffer()); } @@ -691,7 +746,8 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi Renderer::Desc desc; desc.width = gWindowWidth; desc.height = gWindowHeight; - desc.adapter = gOptions.adapter; + desc.adapter = options.adapter; + desc.requiredFeatures = options.renderFeatures; window = renderer_test::Window::create(); SLANG_RETURN_ON_FAIL(window->initialize(gWindowWidth, gWindowHeight)); @@ -699,14 +755,14 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi SlangResult res = renderer->initialize(desc, window->getHandle()); if (SLANG_FAILED(res)) { - if (!gOptions.onlyStartup) + if (!options.onlyStartup) { fprintf(stderr, "Unable to initialize renderer %s\n", rendererName.getBuffer()); } return res; } - for (const auto& feature : gOptions.renderFeatures) + for (const auto& feature : options.renderFeatures) { // If doesn't have required feature... we have to give up if (!renderer->hasFeature(feature.getUnownedSlice())) @@ -717,14 +773,14 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi } // If the only test is we can startup, then we are done - if (gOptions.onlyStartup) + if (options.onlyStartup) { return SLANG_OK; } { RefPtr<RenderTestApp> app(new RenderTestApp); - SLANG_RETURN_ON_FAIL(app->initialize(session, renderer, gOptions, input)); + SLANG_RETURN_ON_FAIL(app->initialize(session, renderer, options, input)); window->show(); return window->runLoop(app); } @@ -758,7 +814,7 @@ int main(int argc, char** argv) using namespace Slang; SlangSession* session = spCreateSession(nullptr); - TestToolUtil::setSessionDefaultPrelude(argv[0], session); + TestToolUtil::setSessionDefaultPreludeFromExePath(argv[0], session); auto stdWriters = StdWriters::initDefaultSingleton(); diff --git a/tools/render-test/slang-support.cpp b/tools/render-test/slang-support.cpp index da6ceb010..78c730cab 100644 --- a/tools/render-test/slang-support.cpp +++ b/tools/render-test/slang-support.cpp @@ -50,7 +50,7 @@ static gfx::StageType _translateStage(SlangStage slangStage) } } -/* static */ SlangResult ShaderCompilerUtil::compileProgram(SlangSession* session, const Input& input, const ShaderCompileRequest& request, Output& out) +/* static */ SlangResult ShaderCompilerUtil::compileProgram(SlangSession* session, const Options& options, const Input& input, const ShaderCompileRequest& request, Output& out) { out.reset(); @@ -137,7 +137,7 @@ static gfx::StageType _translateStage(SlangStage slangStage) Index explicitEntryPointCount = request.entryPoints.getCount(); for(Index ee = 0; ee < explicitEntryPointCount; ++ee) { - if(gOptions.dontAddDefaultEntryPoints) + if(options.dontAddDefaultEntryPoints) { // If default entry points are not to be added, then // the `request.entryPoints` array should have been @@ -359,7 +359,7 @@ static gfx::StageType _translateStage(SlangStage slangStage) compileRequest.globalSpecializationArgs = layout.globalSpecializationArgs; compileRequest.entryPointSpecializationArgs = layout.entryPointSpecializationArgs; - return ShaderCompilerUtil::compileProgram(session, input, compileRequest, output.output); + return ShaderCompilerUtil::compileProgram(session, options, input, compileRequest, output.output); } } // renderer_test diff --git a/tools/render-test/slang-support.h b/tools/render-test/slang-support.h index 99509914e..5e38c8c69 100644 --- a/tools/render-test/slang-support.h +++ b/tools/render-test/slang-support.h @@ -87,7 +87,7 @@ struct ShaderCompilerUtil static SlangResult readSource(const Slang::String& inSourcePath, List<char>& outSourceText); - static SlangResult compileProgram(SlangSession* session, const Input& input, const ShaderCompileRequest& request, Output& out); + static SlangResult compileProgram(SlangSession* session, const Options& options, const Input& input, const ShaderCompileRequest& request, Output& out); }; diff --git a/tools/slang-test/options.cpp b/tools/slang-test/options.cpp index eee099965..27b759a0e 100644 --- a/tools/slang-test/options.cpp +++ b/tools/slang-test/options.cpp @@ -266,16 +266,6 @@ static bool _isSubCommand(const char* arg) return res; } } - else if (strcmp(arg, "-nvapi-path") == 0) - { - if (argCursor == argEnd) - { - stdError.print("error: expected operand for '%s'\n", arg); - return SLANG_FAIL; - } - - optionsOut->nvapiPath = *argCursor++; - } else { stdError.print("unknown option '%s'\n", arg); diff --git a/tools/slang-test/options.h b/tools/slang-test/options.h index 220293ba0..a8c2e3852 100644 --- a/tools/slang-test/options.h +++ b/tools/slang-test/options.h @@ -98,9 +98,6 @@ struct Options // The adapter to use. If empty will match first found adapter. Slang::String adapter; - // The path to NVAPI if available. - Slang::String nvapiPath; - /// Parse the args, report any errors into stdError, and write the results into optionsOut static SlangResult parse(int argc, char** argv, TestCategorySet* categorySet, Slang::WriterHelper stdError, Options* optionsOut); }; diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp index 1144b4034..b2e2bb55c 100644 --- a/tools/slang-test/slang-test-main.cpp +++ b/tools/slang-test/slang-test-main.cpp @@ -495,6 +495,7 @@ Result spawnAndWaitSharedLibrary(TestContext* context, const String& testPath, c if (options.shouldBeVerbose) { CommandLine testCmdLine; + testCmdLine.setExecutableFilename("slang-test"); if (options.binDir.getLength()) @@ -531,8 +532,10 @@ Result spawnAndWaitSharedLibrary(TestContext* context, const String& testPath, c stdWriters.setWriter(SLANG_WRITER_CHANNEL_DIAGNOSTIC, &stdError); } + String exePath = Path::combine(context->exeDirectoryPath, exeName); + List<const char*> args; - args.add(exeName.getBuffer()); + args.add(exePath.getBuffer()); for (Index i = 0; i < cmdLine.m_args.getCount(); ++i) { args.add(cmdLine.m_args[i].value.getBuffer()); @@ -3191,7 +3194,7 @@ SlangResult innerMain(int argc, char** argv) // The context holds useful things used during testing TestContext context; - SLANG_RETURN_ON_FAIL(SLANG_FAILED(context.init())) + SLANG_RETURN_ON_FAIL(SLANG_FAILED(context.init(argv[0]))) auto& categorySet = context.categorySet; @@ -3272,19 +3275,9 @@ SlangResult innerMain(int argc, char** argv) Options& options = context.options; - // Set up the prelude - { - TestToolUtil::PreludeInfo info; - info.exePath = argv[0]; - - if (options.nvapiPath.getLength()) - { - info.nvapiPath = options.nvapiPath.getBuffer(); - } - - TestToolUtil::setSessionDefaultPrelude(info, context.getSession()); - } - + // Set up the prelude/s + TestToolUtil::setSessionDefaultPreludeFromExePath(argv[0], context.getSession()); + if (options.outputMode == TestOutputMode::TeamCity) { // On TeamCity CI there is an issue with unix/linux targets where test system may be different from the build system diff --git a/tools/slang-test/test-context.cpp b/tools/slang-test/test-context.cpp index 8fa5cb345..2872ddb47 100644 --- a/tools/slang-test/test-context.cpp +++ b/tools/slang-test/test-context.cpp @@ -5,6 +5,8 @@ #include "../../source/core/slang-string-util.h" #include "../../source/core/slang-shared-library.h" +#include "../../source/core/slang-test-tool-util.h" + #include <stdio.h> #include <stdlib.h> @@ -15,14 +17,14 @@ TestContext::TestContext() m_session = nullptr; } -Result TestContext::init() +Result TestContext::init(const char* exePath) { m_session = spCreateSession(nullptr); if (!m_session) { return SLANG_FAIL; } - + SLANG_RETURN_ON_FAIL(TestToolUtil::getExeDirectoryPath(exePath, exeDirectoryPath)); return SLANG_OK; } diff --git a/tools/slang-test/test-context.h b/tools/slang-test/test-context.h index ab0a00b40..46a42f3fa 100644 --- a/tools/slang-test/test-context.h +++ b/tools/slang-test/test-context.h @@ -83,7 +83,7 @@ class TestContext /// Get the slang session SlangSession* getSession() const { return m_session; } - SlangResult init(); + SlangResult init(const char* exePath); /// Get the inner main function (from shared library) InnerMainFunc getInnerMainFunc(const Slang::String& dirPath, const Slang::String& name); @@ -126,6 +126,8 @@ class TestContext Slang::RefPtr<Slang::DownstreamCompilerSet> compilerSet; + Slang::String exeDirectoryPath; + protected: struct SharedLibraryTool { |
