summaryrefslogtreecommitdiffstats
path: root/tools/render-test/render-vk.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2018-03-21 14:28:43 -0400
committerTim Foley <tfoleyNV@users.noreply.github.com>2018-03-21 11:28:43 -0700
commitd421988f91d0d6fda78b9aea4cba763f9c662ffe (patch)
tree4207ebec4a744f67df540388133033753cffa359 /tools/render-test/render-vk.cpp
parent98b8e0c809ceab84cee25389e54f3f37d220d95e (diff)
First pass impls on ComPtr and reorganise Renderer (#450)
* Fixed some small typos in api-users-guide.md * Fix some small typos in slang-test/main.cpp, render-test/render-d3d11.cpp * Remove exit() calls from test code. Added Slang::Result, which works in the same way as COM HRESULT. * FIx bug introduced when moving to Slang::Result - handling E_INVALIDARG on Dx11. * Fix the testing of feature levels on Dx11 renderer. * First attempt at README.md for slang-test. * Tidied up the slang-test README.md file. * Fix some small typos in tools/slang-test/main.cpp * Fix spaces -> tabs problems. Fix some small types. * Refactor Renderer implementations such that: * Class definition does not contain long implementation/s * Removed unused globals * Ordered implementation after class definition * Made renderer specific classes child classes, and use Impl postfix to differentiate * Converted tabs into spaces * First pass at Slang::ComPtr. Added slang-defines.h which sets up some fairly commonly used defines such as SLANG_FORCE_INLINE, compiler detection, os detection, and some other cross platform features.
Diffstat (limited to 'tools/render-test/render-vk.cpp')
-rw-r--r--tools/render-test/render-vk.cpp1398
1 files changed, 693 insertions, 705 deletions
diff --git a/tools/render-test/render-vk.cpp b/tools/render-test/render-vk.cpp
index 1f8e11aa6..2c74c8883 100644
--- a/tools/render-test/render-vk.cpp
+++ b/tools/render-test/render-vk.cpp
@@ -81,6 +81,92 @@ namespace renderer_test {
class VKRenderer : public Renderer, public ShaderCompiler
{
public:
+ // Renderer implementation
+ virtual SlangResult initialize(void* inWindowHandle) override;
+ virtual void setClearColor(float const* color) override;
+ virtual void clearFrame() override;
+ virtual void presentFrame() override;
+ virtual SlangResult captureScreenShot(char const* outputPath) override;
+ virtual void serializeOutput(BindingState* state, const char * fileName) override;
+ virtual Buffer* createBuffer(BufferDesc const& desc) override;
+ virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) override;
+ virtual BindingState * createBindingState(const ShaderInputLayout & layout) override;
+ virtual ShaderCompiler* getShaderCompiler() override;
+ virtual void* map(Buffer* buffer, MapFlavor flavor) override;
+ virtual void unmap(Buffer* buffer) override;
+ virtual void setInputLayout(InputLayout* inputLayout) override;
+ virtual void setPrimitiveTopology(PrimitiveTopology topology) override;
+ virtual void setBindingState(BindingState * state);
+ virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets) override;
+ virtual void setShaderProgram(ShaderProgram* inProgram) override;
+ virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets) override;
+ virtual void draw(UInt vertexCount, UInt startVertex) override;
+ virtual void dispatchCompute(int x, int y, int z) override;
+
+ // ShaderCompiler implementation
+ virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override;
+
+ protected:
+
+ struct BufferImpl
+ {
+ VkBuffer buffer;
+ VkDeviceMemory memory;
+ };
+
+ struct ShaderProgramImpl
+ {
+ VkPipelineShaderStageCreateInfo compute;
+ VkPipelineShaderStageCreateInfo vertex;
+ VkPipelineShaderStageCreateInfo fragment;
+ };
+
+ struct BindingImpl
+ {
+ ShaderInputType type;
+ InputBufferType bufferType; // Only valid if `type` is `Buffer`
+
+ VkImageView srv;
+ VkBufferView uav;
+ VkBuffer buffer;
+ VkSampler samplerState;
+
+ int binding = 0;
+ bool isOutput = false;
+ int bufferLength = 0;
+ };
+
+ struct BindingStateImpl
+ {
+ Slang::List<BindingImpl> bindings;
+ int numRenderTargets;
+ };
+
+ struct InputLayoutImpl
+ {
+ };
+
+ VkBool32 handleDebugMessage(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
+ size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg);
+ BufferImpl createBufferImpl(size_t bufferSize, VkBufferUsageFlags usage, VkMemoryPropertyFlags reqMemoryProperties, void const* initData = nullptr);
+
+ VkCommandBuffer getCommandBuffer();
+ VkCommandBuffer beginCommandBuffer();
+ void flushCommandBuffer(VkCommandBuffer commandBuffer);
+
+ uint32_t getMemoryTypeIndex(uint32_t inTypeBits, VkMemoryPropertyFlags properties);
+
+ VkPipelineShaderStageCreateInfo compileEntryPoint(const ShaderCompileRequest::EntryPoint& entryPointRequest, VkShaderStageFlagBits stage);
+
+ void createInputTexture(const InputTextureDesc& inputDesc, VkImageView& viewOut);
+ void createInputSampler(const InputSamplerDesc& inputDesc, VkSampler& stateOut);
+ void createInputBuffer(const ShaderInputLayoutEntry& entry, const InputBufferDesc& bufferDesc, const Slang::List<unsigned int>& bufferData,
+ VkBuffer& bufferOut, VkBufferView& uavOut, VkImageView& srvOut);
+
+ static SlangResult toSlangResult(VkResult res);
+ static void checkResult(VkResult result);
+ static VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
+ size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void* pUserData);
VkInstance instance;
VkPhysicalDevice physicalDevice;
@@ -94,6 +180,10 @@ public:
VkSubmitInfo submitInfo;
VkDebugReportCallbackEXT debugReportCallback;
+ BindingStateImpl* currentBindingState = nullptr;
+ ShaderProgramImpl* currentProgram = nullptr;
+
+ float clearColor[4];
#define DECLARE_PROC(NAME) PFN_##NAME NAME;
DECLARE_PROC(vkGetInstanceProcAddr);
@@ -101,605 +191,555 @@ public:
FOREACH_INSTANCE_PROC(DECLARE_PROC)
FOREACH_DEVICE_PROC(DECLARE_PROC)
#undef DECLARE_PROC
+
+};
- // Renderer interface
-
- static SlangResult toSlangResult(VkResult res)
- {
- return (res == VK_SUCCESS) ? SLANG_OK : SLANG_FAIL;
- }
- void checkResult(VkResult result)
- {
- assert(result == VK_SUCCESS);
- }
-
- VkBool32 handleDebugMessage(
- VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT objType,
- uint64_t srcObject,
- size_t location,
- int32_t msgCode,
- const char* pLayerPrefix,
- const char* pMsg)
- {
- char const* severity = "message";
- if(flags & VK_DEBUG_REPORT_WARNING_BIT_EXT)
- severity = "warning";
- if(flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
- severity = "error";
-
- char buffer[1024];
- sprintf_s(buffer,
- "%s: %s %d: %s\n",
- pLayerPrefix,
- severity,
- msgCode,
- pMsg);
-
- fprintf(stderr, "%s", buffer);
- fflush(stderr);
-
- OutputDebugStringA(buffer);
-
- return VK_FALSE;
- }
+Renderer* createVKRenderer()
+{
+ return new VKRenderer();
+}
- static VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback(
- VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT objType,
- uint64_t srcObject,
- size_t location,
- int32_t msgCode,
- const char* pLayerPrefix,
- const char* pMsg,
- void* pUserData)
- {
- return ((VKRenderer*) pUserData)->handleDebugMessage(
- flags, objType, srcObject, location, msgCode, pLayerPrefix, pMsg);
- }
+/* static */SlangResult VKRenderer::toSlangResult(VkResult res)
+{
+ return (res == VK_SUCCESS) ? SLANG_OK : SLANG_FAIL;
+}
- virtual SlangResult initialize(void* inWindowHandle) override
- {
- char const* dynamicLibraryName = "vulkan-1.dll";
- HMODULE vulkan = LoadLibraryA(dynamicLibraryName);
- if(!vulkan)
- {
- fprintf(stderr, "error: failed load '%s'\n", dynamicLibraryName);
- return SLANG_FAIL;
- }
+void VKRenderer::checkResult(VkResult result)
+{
+ assert(result == VK_SUCCESS);
+}
- vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) GetProcAddress(vulkan, "vkGetInstanceProcAddr");
- if(!vkGetInstanceProcAddr)
- {
- fprintf(stderr, "error: failed load symbol 'vkGetInstanceProcAddr'\n");
- return SLANG_FAIL;
- }
+VkBool32 VKRenderer::handleDebugMessage(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
+ size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg)
+{
+ char const* severity = "message";
+ if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT)
+ severity = "warning";
+ if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
+ severity = "error";
+
+ char buffer[1024];
+ sprintf_s(buffer,
+ "%s: %s %d: %s\n",
+ pLayerPrefix,
+ severity,
+ msgCode,
+ pMsg);
+
+ fprintf(stderr, "%s", buffer);
+ fflush(stderr);
+
+ OutputDebugStringA(buffer);
+
+ return VK_FALSE;
+}
- VkApplicationInfo applicationInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
- applicationInfo.pApplicationName = "slang-render-test";
- applicationInfo.pEngineName = "slang-render-test";
- applicationInfo.apiVersion = VK_API_VERSION_1_0;
+/* static */VKAPI_ATTR VkBool32 VKAPI_CALL VKRenderer::debugMessageCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
+ size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void* pUserData)
+{
+ return ((VKRenderer*)pUserData)->handleDebugMessage(flags, objType, srcObject, location, msgCode, pLayerPrefix, pMsg);
+}
- char const* instanceExtensions[] = {
- VK_KHR_SURFACE_EXTENSION_NAME,
-#ifdef _WIN32
- VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
-#else
-#endif
+VkCommandBuffer VKRenderer::getCommandBuffer()
+{
+ VkCommandBufferAllocateInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
+ info.commandPool = commandPool;
+ info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ info.commandBufferCount = 1;
-#if ENABLE_VALIDATION_LAYER
- VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
-#endif
- };
+ VkCommandBuffer commandBuffer;
+ checkResult(vkAllocateCommandBuffers(
+ device, &info, &commandBuffer));
- VkInstanceCreateInfo instanceCreateInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
- instanceCreateInfo.pApplicationInfo = &applicationInfo;
+ return commandBuffer;
+}
- instanceCreateInfo.enabledExtensionCount = sizeof(instanceExtensions) / sizeof(instanceExtensions[0]);
- instanceCreateInfo.ppEnabledExtensionNames = &instanceExtensions[0];
+VkCommandBuffer VKRenderer::beginCommandBuffer()
+{
+ VkCommandBuffer commandBuffer = getCommandBuffer();
-#if ENABLE_VALIDATION_LAYER
+ VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
+ checkResult(vkBeginCommandBuffer(commandBuffer, &beginInfo));
- uint32_t layerCount = 1;
- const char *layerNames[] = {
- "VK_LAYER_LUNARG_standard_validation"
- };
+ return commandBuffer;
+}
- instanceCreateInfo.enabledLayerCount = layerCount;
- instanceCreateInfo.ppEnabledLayerNames = layerNames;
-#endif
+void VKRenderer::flushCommandBuffer(VkCommandBuffer commandBuffer)
+{
+ checkResult(vkEndCommandBuffer(commandBuffer));
- instance = 0;
+ VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &commandBuffer;
-#define LOAD_INSTANCE_PROC(NAME) NAME = (PFN_##NAME) vkGetInstanceProcAddr(instance, #NAME);
+ checkResult(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
+ checkResult(vkQueueWaitIdle(queue));
- FOREACH_GLOBAL_PROC(LOAD_INSTANCE_PROC);
+ vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
+}
- RETURN_ON_VK_FAIL(vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
+VKRenderer::BufferImpl VKRenderer::createBufferImpl(size_t bufferSize, VkBufferUsageFlags usage, VkMemoryPropertyFlags reqMemoryProperties, void const* initData)
+{
+ if (initData)
+ {
+ // TODO: what if we are allocating it as CPU-writable anyway?
+ usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ }
- FOREACH_INSTANCE_PROC(LOAD_INSTANCE_PROC);
+ VkBufferCreateInfo bufferCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+ bufferCreateInfo.size = bufferSize;
+ bufferCreateInfo.usage = usage;
-#undef LOAD_INSTANCE_PROC
+ VkBuffer buffer;
+ checkResult(vkCreateBuffer(
+ device, &bufferCreateInfo, nullptr, &buffer));
+ VkMemoryRequirements memoryReqs = {};
+ vkGetBufferMemoryRequirements(device, buffer, &memoryReqs);
-#if ENABLE_VALIDATION_LAYER
- VkDebugReportFlagsEXT debugFlags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
+ uint32_t memoryTypeIndex = getMemoryTypeIndex(
+ memoryReqs.memoryTypeBits, reqMemoryProperties);
- VkDebugReportCallbackCreateInfoEXT debugCreateInfo = { VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT };
- debugCreateInfo.pfnCallback = &debugMessageCallback;
- debugCreateInfo.pUserData = this;
- debugCreateInfo.flags = debugFlags;
+ VkMemoryPropertyFlags actualMemoryProperites = deviceMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags;
- RETURN_ON_VK_FAIL(vkCreateDebugReportCallbackEXT(instance, &debugCreateInfo, nullptr, &debugReportCallback));
+ VkMemoryAllocateInfo allocateInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
+ allocateInfo.allocationSize = memoryReqs.size;
+ allocateInfo.memoryTypeIndex = memoryTypeIndex;
-#endif
+ VkDeviceMemory memory;
+ checkResult(vkAllocateMemory(
+ device, &allocateInfo, nullptr, &memory));
- uint32_t physicalDeviceCount = 0;
- RETURN_ON_VK_FAIL(vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr));
+ checkResult(vkBindBufferMemory(
+ device, buffer, memory, 0));
- VkPhysicalDevice* physicalDevices = (VkPhysicalDevice*)alloca(
- physicalDeviceCount * sizeof(VkPhysicalDevice));
- RETURN_ON_VK_FAIL(vkEnumeratePhysicalDevices(
- instance, &physicalDeviceCount, physicalDevices));
+ if (initData)
+ {
+ // TODO: only create staging buffer if the memory type
+ // used for the buffer doesn't let us fill things in
+ // directly.
- uint32_t selectedDeviceIndex = 0;
- // TODO: allow override of selected device
- physicalDevice = physicalDevices[selectedDeviceIndex];
+ BufferImpl staging = createBufferImpl(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
- vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
- vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
- vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties);
+ // Copy into staging buffer
+ void* mappedData = nullptr;
+ checkResult(vkMapMemory(device, staging.memory, 0, bufferSize, 0, &mappedData));
+ memcpy(mappedData, initData, bufferSize);
+ vkUnmapMemory(device, staging.memory);
- uint32_t queueFamilyCount = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(
- physicalDevice, &queueFamilyCount, nullptr);
+ // Copy from staging buffer to real buffer
+ VkCommandBuffer commandBuffer = beginCommandBuffer();
- VkQueueFamilyProperties* queueFamilies = (VkQueueFamilyProperties*)alloca(
- queueFamilyCount * sizeof(VkQueueFamilyProperties));
- vkGetPhysicalDeviceQueueFamilyProperties(
- physicalDevice, &queueFamilyCount, queueFamilies);
+ VkBufferCopy copyInfo = {};
+ copyInfo.size = bufferSize;
+ vkCmdCopyBuffer(commandBuffer, staging.buffer, buffer, 1, &copyInfo);
- // Find a queue that can service our needs
- VkQueueFlags reqQueueFlags =
- VK_QUEUE_GRAPHICS_BIT
- | VK_QUEUE_COMPUTE_BIT;
+ flushCommandBuffer(commandBuffer);
- uint32_t queueFamilyIndex = uint32_t(-1);
- for (uint32_t qq = 0; qq < queueFamilyCount; ++qq)
- {
- if ((queueFamilies[qq].queueFlags & reqQueueFlags) == reqQueueFlags)
- {
- queueFamilyIndex = qq;
- break;
- }
- }
- assert(queueFamilyIndex < queueFamilyCount);
+ // Now destroy the staging buffer
+ vkDestroyBuffer(device, staging.buffer, nullptr);
+ vkFreeMemory(device, staging.memory, nullptr);
+ }
- float queuePriority = 0.0f;
- VkDeviceQueueCreateInfo queueCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
- queueCreateInfo.queueFamilyIndex = queueFamilyIndex;
- queueCreateInfo.queueCount = 1;
- queueCreateInfo.pQueuePriorities = &queuePriority;
+ BufferImpl impl;
+ impl.buffer = buffer;
+ impl.memory = memory;
+ return impl;
+}
- char const* const deviceExtensions[] =
+uint32_t VKRenderer::getMemoryTypeIndex(uint32_t inTypeBits, VkMemoryPropertyFlags properties)
+{
+ uint32_t typeBits = inTypeBits;
+ uint32_t typeIndex = 0;
+ while (typeBits)
+ {
+ if ((deviceMemoryProperties.memoryTypes[typeIndex].propertyFlags & properties) == properties)
{
- VK_KHR_SWAPCHAIN_EXTENSION_NAME,
- };
+ return typeIndex;
+ }
+ typeIndex++;
+ typeBits >>= 1;
+ }
- VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
- deviceCreateInfo.queueCreateInfoCount = 1;
- deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
- deviceCreateInfo.pEnabledFeatures = &enabledFeatures;
+ assert(!"failed to find a usable memory type");
+ return uint32_t(-1);
+}
- deviceCreateInfo.enabledExtensionCount = sizeof(deviceExtensions) / sizeof(deviceExtensions[0]);
- deviceCreateInfo.ppEnabledExtensionNames = &deviceExtensions[0];
+void VKRenderer::createInputTexture(const InputTextureDesc& inputDesc, VkImageView& viewOut)
+{
+ TextureData texData;
+ generateTextureData(texData, inputDesc);
+ assert(!"unimplemented");
+}
- RETURN_ON_VK_FAIL(vkCreateDevice(
- physicalDevice, &deviceCreateInfo, nullptr, &device));
+void VKRenderer::createInputSampler(const InputSamplerDesc& inputDesc, VkSampler& stateOut)
+{
+ assert(!"unimplemented");
+}
-#define LOAD_DEVICE_PROC(NAME) NAME = (PFN_##NAME) vkGetDeviceProcAddr(device, #NAME);
- FOREACH_DEVICE_PROC(LOAD_DEVICE_PROC)
-#undef LOAD_DEVICE_PROC
+void VKRenderer::createInputBuffer(const ShaderInputLayoutEntry& entry, const InputBufferDesc& bufferDesc, const Slang::List<unsigned int>& bufferData,
+ VkBuffer& bufferOut, VkBufferView& uavOut, VkImageView& srvOut)
+{
+ size_t bufferSize = bufferData.Count() * sizeof(unsigned int);
+ void const* initData = bufferData.Buffer();
- // Create a command pool
+ VkBufferUsageFlags usage = 0;
+ VkMemoryPropertyFlags reqMemoryProperties = 0;
- VkCommandPoolCreateInfo commandPoolCreateInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
- commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex;
- commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ switch (bufferDesc.type)
+ {
+ case InputBufferType::ConstantBuffer:
+ usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ reqMemoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ break;
- RETURN_ON_VK_FAIL(vkCreateCommandPool(
- device, &commandPoolCreateInfo, nullptr, &commandPool));
+ case InputBufferType::StorageBuffer:
+ usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ reqMemoryProperties = 0;
+ break;
+ }
- vkGetDeviceQueue(
- device,
- queueFamilyIndex,
- 0,
- &queue);
+ // If we are going to read back from the buffer, be sure to request
+ // the required access.
+ if (entry.isOutput)
+ {
+ usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+ }
- // set up swap chain
+ BufferImpl bufferImpl = createBufferImpl(bufferSize, usage, reqMemoryProperties, initData);
+ // TODO: need to hang onto the `memory` field so
+ // that we can release it when we are done.
+ bufferOut = bufferImpl.buffer;
- // create command buffers
+ // Fill in any views needed
+ switch (bufferDesc.type)
+ {
+ case InputBufferType::ConstantBuffer:
+ break;
- // depth/stencil?
+ case InputBufferType::StorageBuffer:
+ {
+ }
+ break;
+ }
+}
- // render pass?
+VkPipelineShaderStageCreateInfo VKRenderer::compileEntryPoint(const ShaderCompileRequest::EntryPoint& entryPointRequest, VkShaderStageFlagBits stage)
+{
+ char const* dataBegin = entryPointRequest.source.dataBegin;
+ char const* dataEnd = entryPointRequest.source.dataEnd;
- // pipeline cache
+ // We need to make a copy of the code, since the Slang compiler
+ // will free the memory after a compile request is closed.
+ size_t codeSize = dataEnd - dataBegin;
+ char* codeBegin = (char*)malloc(codeSize);
+ memcpy(codeBegin, dataBegin, codeSize);
- // frame buffer
+ VkShaderModuleCreateInfo moduleCreateInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
+ moduleCreateInfo.pCode = (uint32_t*)codeBegin;
+ moduleCreateInfo.codeSize = codeSize;
+ VkShaderModule module;
+ checkResult(vkCreateShaderModule(device, &moduleCreateInfo, nullptr, &module));
+ //::free(codeBegin);
- // create semaphores for sync
+ VkPipelineShaderStageCreateInfo shaderStageCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
+ shaderStageCreateInfo.stage = stage;
- return SLANG_OK;
- }
+ shaderStageCreateInfo.module = module;
+ shaderStageCreateInfo.pName = "main";
+ return shaderStageCreateInfo;
+}
- float clearColor[4];
- virtual void setClearColor(float const* color) override
- {
- for(int ii = 0; ii < 4; ++ii)
- clearColor[ii] = color[ii];
- }
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
- virtual void clearFrame() override
+SlangResult VKRenderer::initialize(void* inWindowHandle)
+{
+ char const* dynamicLibraryName = "vulkan-1.dll";
+ HMODULE vulkan = LoadLibraryA(dynamicLibraryName);
+ if (!vulkan)
{
+ fprintf(stderr, "error: failed load '%s'\n", dynamicLibraryName);
+ return SLANG_FAIL;
}
- virtual void presentFrame() override
+ vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)GetProcAddress(vulkan, "vkGetInstanceProcAddr");
+ if (!vkGetInstanceProcAddr)
{
+ fprintf(stderr, "error: failed load symbol 'vkGetInstanceProcAddr'\n");
+ return SLANG_FAIL;
}
- virtual SlangResult captureScreenShot(char const* outputPath) override
- {
- return SLANG_FAIL;
- }
+ VkApplicationInfo applicationInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
+ applicationInfo.pApplicationName = "slang-render-test";
+ applicationInfo.pEngineName = "slang-render-test";
+ applicationInfo.apiVersion = VK_API_VERSION_1_0;
- virtual ShaderCompiler* getShaderCompiler() override
- {
- return this;
- }
+ char const* instanceExtensions[] = {
+ VK_KHR_SURFACE_EXTENSION_NAME,
+#ifdef _WIN32
+ VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
+#else
+#endif
- VkCommandBuffer getCommandBuffer()
- {
- VkCommandBufferAllocateInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
- info.commandPool = commandPool;
- info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- info.commandBufferCount = 1;
+#if ENABLE_VALIDATION_LAYER
+ VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
+#endif
+ };
- VkCommandBuffer commandBuffer;
- checkResult(vkAllocateCommandBuffers(
- device, &info, &commandBuffer));
+ VkInstanceCreateInfo instanceCreateInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
+ instanceCreateInfo.pApplicationInfo = &applicationInfo;
- return commandBuffer;
- }
+ instanceCreateInfo.enabledExtensionCount = sizeof(instanceExtensions) / sizeof(instanceExtensions[0]);
+ instanceCreateInfo.ppEnabledExtensionNames = &instanceExtensions[0];
- VkCommandBuffer beginCommandBuffer()
- {
- VkCommandBuffer commandBuffer = getCommandBuffer();
+#if ENABLE_VALIDATION_LAYER
- VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
- checkResult(vkBeginCommandBuffer(commandBuffer, &beginInfo));
+ uint32_t layerCount = 1;
+ const char *layerNames[] = {
+ "VK_LAYER_LUNARG_standard_validation"
+ };
- return commandBuffer;
- }
+ instanceCreateInfo.enabledLayerCount = layerCount;
+ instanceCreateInfo.ppEnabledLayerNames = layerNames;
+#endif
- void flushCommandBuffer(VkCommandBuffer commandBuffer)
- {
- checkResult(vkEndCommandBuffer(commandBuffer));
+ instance = 0;
- VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &commandBuffer;
+#define LOAD_INSTANCE_PROC(NAME) NAME = (PFN_##NAME) vkGetInstanceProcAddr(instance, #NAME);
- checkResult(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
- checkResult(vkQueueWaitIdle(queue));
+ FOREACH_GLOBAL_PROC(LOAD_INSTANCE_PROC);
- vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
- }
+ RETURN_ON_VK_FAIL(vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
- struct BufferImpl
- {
- VkBuffer buffer;
- VkDeviceMemory memory;
- };
+ FOREACH_INSTANCE_PROC(LOAD_INSTANCE_PROC);
- BufferImpl createBufferImpl(
- size_t bufferSize,
- VkBufferUsageFlags usage,
- VkMemoryPropertyFlags reqMemoryProperties,
- void const* initData = nullptr)
- {
- if( initData )
- {
- // TODO: what if we are allocating it as CPU-writable anyway?
- usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- }
+#undef LOAD_INSTANCE_PROC
- VkBufferCreateInfo bufferCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
- bufferCreateInfo.size = bufferSize;
- bufferCreateInfo.usage = usage;
- VkBuffer buffer;
- checkResult(vkCreateBuffer(
- device, &bufferCreateInfo, nullptr, &buffer));
+#if ENABLE_VALIDATION_LAYER
+ VkDebugReportFlagsEXT debugFlags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
- VkMemoryRequirements memoryReqs = {};
- vkGetBufferMemoryRequirements(device, buffer, &memoryReqs);
+ VkDebugReportCallbackCreateInfoEXT debugCreateInfo = { VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT };
+ debugCreateInfo.pfnCallback = &debugMessageCallback;
+ debugCreateInfo.pUserData = this;
+ debugCreateInfo.flags = debugFlags;
- uint32_t memoryTypeIndex = getMemoryTypeIndex(
- memoryReqs.memoryTypeBits, reqMemoryProperties);
+ RETURN_ON_VK_FAIL(vkCreateDebugReportCallbackEXT(instance, &debugCreateInfo, nullptr, &debugReportCallback));
- VkMemoryPropertyFlags actualMemoryProperites = deviceMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags;
+#endif
- VkMemoryAllocateInfo allocateInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
- allocateInfo.allocationSize = memoryReqs.size;
- allocateInfo.memoryTypeIndex = memoryTypeIndex;
+ uint32_t physicalDeviceCount = 0;
+ RETURN_ON_VK_FAIL(vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr));
- VkDeviceMemory memory;
- checkResult(vkAllocateMemory(
- device, &allocateInfo, nullptr, &memory));
+ VkPhysicalDevice* physicalDevices = (VkPhysicalDevice*)alloca(
+ physicalDeviceCount * sizeof(VkPhysicalDevice));
+ RETURN_ON_VK_FAIL(vkEnumeratePhysicalDevices(
+ instance, &physicalDeviceCount, physicalDevices));
- checkResult(vkBindBufferMemory(
- device, buffer, memory, 0));
+ uint32_t selectedDeviceIndex = 0;
+ // TODO: allow override of selected device
+ physicalDevice = physicalDevices[selectedDeviceIndex];
- if( initData )
- {
- // TODO: only create staging buffer if the memory type
- // used for the buffer doesn't let us fill things in
- // directly.
-
- BufferImpl staging = createBufferImpl(
- bufferSize,
- VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
-
- // Copy into staging buffer
- void* mappedData = nullptr;
- checkResult(vkMapMemory(device, staging.memory, 0, bufferSize, 0, &mappedData));
- memcpy(mappedData, initData, bufferSize);
- vkUnmapMemory(device, staging.memory);
-
- // Copy from staging buffer to real buffer
- VkCommandBuffer commandBuffer = beginCommandBuffer();
-
- VkBufferCopy copyInfo = {};
- copyInfo.size = bufferSize;
- vkCmdCopyBuffer(
- commandBuffer,
- staging.buffer,
- buffer,
- 1,
- &copyInfo);
-
- flushCommandBuffer(commandBuffer);
-
- // Now destroy the staging buffer
- vkDestroyBuffer(device, staging.buffer, nullptr);
- vkFreeMemory(device, staging.memory, nullptr);
- }
+ vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
+ vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
+ vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties);
- BufferImpl impl;
- impl.buffer = buffer;
- impl.memory = memory;
- return impl;
- }
+ uint32_t queueFamilyCount = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(
+ physicalDevice, &queueFamilyCount, nullptr);
- virtual Buffer* createBuffer(BufferDesc const& desc) override
- {
- size_t bufferSize = desc.size;
+ VkQueueFamilyProperties* queueFamilies = (VkQueueFamilyProperties*)alloca(
+ queueFamilyCount * sizeof(VkQueueFamilyProperties));
+ vkGetPhysicalDeviceQueueFamilyProperties(
+ physicalDevice, &queueFamilyCount, queueFamilies);
- VkBufferUsageFlags usage = 0;
- VkMemoryPropertyFlags reqMemoryProperties = 0;
+ // Find a queue that can service our needs
+ VkQueueFlags reqQueueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
- switch( desc.flavor )
+ uint32_t queueFamilyIndex = uint32_t(-1);
+ for (uint32_t qq = 0; qq < queueFamilyCount; ++qq)
+ {
+ if ((queueFamilies[qq].queueFlags & reqQueueFlags) == reqQueueFlags)
{
- case BufferFlavor::Constant:
- usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
- reqMemoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
- break;
-
- case BufferFlavor::Vertex:
- usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
- reqMemoryProperties = 0;
+ queueFamilyIndex = qq;
break;
}
-
- BufferImpl bufferImpl = createBufferImpl(
- bufferSize,
- usage,
- reqMemoryProperties,
- desc.initData);
-
- BufferImpl* bufferPtr = new BufferImpl();
- *bufferPtr = bufferImpl;
- return (Buffer*) bufferPtr;
}
+ assert(queueFamilyIndex < queueFamilyCount);
- struct InputLayoutImpl
+ float queuePriority = 0.0f;
+ VkDeviceQueueCreateInfo queueCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
+ queueCreateInfo.queueFamilyIndex = queueFamilyIndex;
+ queueCreateInfo.queueCount = 1;
+ queueCreateInfo.pQueuePriorities = &queuePriority;
+
+ char const* const deviceExtensions[] =
{
+ VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
- virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) override
- {
- InputLayoutImpl* impl = new InputLayoutImpl();
+ VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
+ deviceCreateInfo.queueCreateInfoCount = 1;
+ deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
+ deviceCreateInfo.pEnabledFeatures = &enabledFeatures;
- // TODO: actually initialize things
+ deviceCreateInfo.enabledExtensionCount = sizeof(deviceExtensions) / sizeof(deviceExtensions[0]);
+ deviceCreateInfo.ppEnabledExtensionNames = &deviceExtensions[0];
- return (InputLayout*) impl;
- }
+ RETURN_ON_VK_FAIL(vkCreateDevice(
+ physicalDevice, &deviceCreateInfo, nullptr, &device));
- virtual void* map(Buffer* buffer, MapFlavor flavor) override
- {
- return nullptr;
- }
+#define LOAD_DEVICE_PROC(NAME) NAME = (PFN_##NAME) vkGetDeviceProcAddr(device, #NAME);
+ FOREACH_DEVICE_PROC(LOAD_DEVICE_PROC)
+#undef LOAD_DEVICE_PROC
- virtual void unmap(Buffer* buffer) override
- {
- }
+ // Create a command pool
- virtual void setInputLayout(InputLayout* inputLayout) override
- {
- }
+ VkCommandPoolCreateInfo commandPoolCreateInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
+ commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex;
+ commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- virtual void setPrimitiveTopology(PrimitiveTopology topology) override
- {
- }
+ RETURN_ON_VK_FAIL(vkCreateCommandPool(
+ device, &commandPoolCreateInfo, nullptr, &commandPool));
- virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets) override
- {
- }
+ vkGetDeviceQueue(device, queueFamilyIndex, 0, &queue);
- struct ShaderProgramImpl
- {
- VkPipelineShaderStageCreateInfo compute;
- VkPipelineShaderStageCreateInfo vertex;
- VkPipelineShaderStageCreateInfo fragment;
- };
+ // set up swap chain
- ShaderProgramImpl* currentProgram = nullptr;
- virtual void setShaderProgram(ShaderProgram* program) override
- {
- currentProgram = (ShaderProgramImpl*) program;
- }
- virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets) override
- {
- }
- virtual void draw(UInt vertexCount, UInt startVertex = 0) override
- {
- }
+ // create command buffers
- struct BindingImpl
- {
- ShaderInputType type;
- InputBufferType bufferType; // Only valid if `type` is `Buffer`
+ // depth/stencil?
- VkImageView srv;
- VkBufferView uav;
- VkBuffer buffer;
- VkSampler samplerState;
+ // render pass?
- int binding = 0;
- bool isOutput = false;
- int bufferLength = 0;
- };
+ // pipeline cache
- struct BindingStateImpl
- {
- Slang::List<BindingImpl> bindings;
- int numRenderTargets;
- };
+ // frame buffer
- uint32_t getMemoryTypeIndex(
- uint32_t inTypeBits,
- VkMemoryPropertyFlags properties)
- {
- uint32_t typeBits = inTypeBits;
- uint32_t typeIndex = 0;
- while( typeBits )
- {
- if((deviceMemoryProperties.memoryTypes[typeIndex].propertyFlags & properties) == properties)
- {
- return typeIndex;
- }
- typeIndex++;
- typeBits >>= 1;
- }
- assert(!"failed to find a usable memory type");
- return uint32_t(-1);
- }
- void createInputBuffer(
- ShaderInputLayoutEntry const& entry,
- InputBufferDesc const& bufferDesc,
- Slang::List<unsigned int> const& bufferData,
- VkBuffer &bufferOut,
- VkBufferView &uavOut,
- VkImageView &srvOut)
- {
- size_t bufferSize = bufferData.Count() * sizeof(unsigned int);
- void const* initData = bufferData.Buffer();
+ // create semaphores for sync
+
+ return SLANG_OK;
+}
- VkBufferUsageFlags usage = 0;
- VkMemoryPropertyFlags reqMemoryProperties = 0;
+void VKRenderer::setClearColor(float const* color)
+{
+ for (int ii = 0; ii < 4; ++ii)
+ clearColor[ii] = color[ii];
+}
- switch( bufferDesc.type )
- {
- case InputBufferType::ConstantBuffer:
+void VKRenderer::clearFrame()
+{
+}
+
+void VKRenderer::presentFrame()
+{
+}
+
+SlangResult VKRenderer::captureScreenShot(char const* outputPath)
+{
+ return SLANG_FAIL;
+}
+
+ShaderCompiler* VKRenderer::getShaderCompiler()
+{
+ return this;
+}
+
+Buffer* VKRenderer::createBuffer(BufferDesc const& desc)
+{
+ size_t bufferSize = desc.size;
+
+ VkBufferUsageFlags usage = 0;
+ VkMemoryPropertyFlags reqMemoryProperties = 0;
+
+ switch (desc.flavor)
+ {
+ case BufferFlavor::Constant:
usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
reqMemoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
break;
- case InputBufferType::StorageBuffer:
- usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ case BufferFlavor::Vertex:
+ usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
reqMemoryProperties = 0;
break;
- }
+ }
- // If we are going to read back from the buffer, be sure to request
- // the required access.
- if(entry.isOutput)
- {
- usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- }
+ BufferImpl bufferImpl = createBufferImpl(
+ bufferSize,
+ usage,
+ reqMemoryProperties,
+ desc.initData);
- BufferImpl bufferImpl = createBufferImpl(
- bufferSize,
- usage,
- reqMemoryProperties,
- initData);
+ BufferImpl* bufferPtr = new BufferImpl();
+ *bufferPtr = bufferImpl;
+ return (Buffer*)bufferPtr;
+}
- // TODO: need to hang onto the `memory` field so
- // that we can release it when we are done.
+InputLayout* VKRenderer::createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount)
+{
+ InputLayoutImpl* impl = new InputLayoutImpl;
- bufferOut = bufferImpl.buffer;
+ // TODO: actually initialize things
- // Fill in any views needed
- switch( bufferDesc.type )
- {
- case InputBufferType::ConstantBuffer:
- break;
+ return (InputLayout*)impl;
+}
- case InputBufferType::StorageBuffer:
- {
- }
- break;
- }
- }
+void* VKRenderer::map(Buffer* buffer, MapFlavor flavor)
+{
+ return nullptr;
+}
- void createInputTexture(
- InputTextureDesc const& inputDesc,
- VkImageView& viewOut)
- {
- TextureData texData;
- generateTextureData(texData, inputDesc);
- assert(!"unimplemented");
- }
+void VKRenderer::unmap(Buffer* buffer)
+{
+}
- void createInputSampler(
- InputSamplerDesc const& inputDesc,
- VkSampler& stateOut)
- {
- assert(!"unimplemented");
- }
+void VKRenderer::setInputLayout(InputLayout* inputLayout)
+{
+}
+
+void VKRenderer::setPrimitiveTopology(PrimitiveTopology topology)
+{
+}
- virtual BindingState* createBindingState(const ShaderInputLayout & layout)
+void VKRenderer::setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets)
+{
+}
+
+void VKRenderer::setShaderProgram(ShaderProgram* program)
+{
+ currentProgram = (ShaderProgramImpl*)program;
+}
+
+void VKRenderer::setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets)
+{
+}
+
+void VKRenderer::draw(UInt vertexCount, UInt startVertex = 0)
+{
+}
+
+BindingState* VKRenderer::createBindingState(const ShaderInputLayout& layout)
+{
+ BindingStateImpl* bindingState = new BindingStateImpl;
+ bindingState->numRenderTargets = layout.numRenderTargets;
+ for (auto & entry : layout.entries)
{
- BindingStateImpl* bindingState = new BindingStateImpl();
- bindingState->numRenderTargets = layout.numRenderTargets;
- for (auto & entry : layout.entries)
+ BindingImpl binding;
+ binding.type = entry.type;
+ binding.binding = entry.hlslBinding;
+ binding.isOutput = entry.isOutput;
+ switch (entry.type)
{
- BindingImpl binding;
- binding.type = entry.type;
- binding.binding = entry.hlslBinding;
- binding.isOutput = entry.isOutput;
- switch (entry.type)
- {
case ShaderInputType::Buffer:
{
createInputBuffer(entry, entry.bufferDesc, entry.bufferData, binding.buffer, binding.uav, binding.srv);
@@ -710,328 +750,276 @@ public:
case ShaderInputType::Texture:
{
createInputTexture(entry.textureDesc, binding.srv);
+ break;
}
- break;
case ShaderInputType::Sampler:
{
createInputSampler(entry.samplerDesc, binding.samplerState);
+ break;
}
- break;
case ShaderInputType::CombinedTextureSampler:
{
throw "not implemented";
+ break;
}
- break;
- }
- bindingState->bindings.Add(binding);
}
-
- return (BindingState*) bindingState;
+ bindingState->bindings.Add(binding);
}
- BindingStateImpl* currentBindingState = nullptr;
- virtual void setBindingState(BindingState * state)
- {
- currentBindingState = (BindingStateImpl*) state;
- }
+ return (BindingState*)bindingState;
+}
- virtual void serializeOutput(BindingState* s, const char * fileName)
- {
- auto state = (BindingStateImpl*) s;
+void VKRenderer::setBindingState(BindingState * state)
+{
+ currentBindingState = (BindingStateImpl*)state;
+}
+
+void VKRenderer::serializeOutput(BindingState* s, const char * fileName)
+{
+ auto state = (BindingStateImpl*)s;
- FILE * f = fopen(fileName, "wb");
- int id = 0;
- for (auto& bb: state->bindings)
+ FILE * f = fopen(fileName, "wb");
+ int id = 0;
+ for (auto& bb : state->bindings)
+ {
+ if (bb.isOutput)
{
- if (bb.isOutput)
+ if (bb.buffer)
{
- if (bb.buffer)
- {
- // create staging buffer
- size_t bufferSize = bb.bufferLength;
- BufferImpl staging = createBufferImpl(
- bufferSize,
- VK_BUFFER_USAGE_TRANSFER_DST_BIT,
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
-
- // Copy from real buffer to staging buffer
- VkCommandBuffer commandBuffer = beginCommandBuffer();
-
- VkBufferCopy copyInfo = {};
- copyInfo.size = bufferSize;
- vkCmdCopyBuffer(
- commandBuffer,
- bb.buffer,
- staging.buffer,
- 1,
- &copyInfo);
-
- flushCommandBuffer(commandBuffer);
-
- // Write out the data from the buffer
- void* mappedData = nullptr;
- checkResult(vkMapMemory(device, staging.memory, 0, bufferSize, 0, &mappedData));
-
- auto ptr = (unsigned int *) mappedData;
- for (auto i = 0u; i < bufferSize / sizeof(unsigned int); i++)
- fprintf(f, "%X\n", ptr[i]);
-
- vkUnmapMemory(device, staging.memory);
-
- // Now destroy the staging buffer
- vkDestroyBuffer(device, staging.buffer, nullptr);
- vkFreeMemory(device, staging.memory, nullptr);
- }
- else
- {
- printf("invalid output type at %d.\n", id);
- }
+ // create staging buffer
+ size_t bufferSize = bb.bufferLength;
+ BufferImpl staging = createBufferImpl(
+ bufferSize,
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+
+ // Copy from real buffer to staging buffer
+ VkCommandBuffer commandBuffer = beginCommandBuffer();
+
+ VkBufferCopy copyInfo = {};
+ copyInfo.size = bufferSize;
+ vkCmdCopyBuffer(
+ commandBuffer,
+ bb.buffer,
+ staging.buffer,
+ 1,
+ &copyInfo);
+
+ flushCommandBuffer(commandBuffer);
+
+ // Write out the data from the buffer
+ void* mappedData = nullptr;
+ checkResult(vkMapMemory(device, staging.memory, 0, bufferSize, 0, &mappedData));
+
+ auto ptr = (unsigned int *)mappedData;
+ for (auto i = 0u; i < bufferSize / sizeof(unsigned int); i++)
+ fprintf(f, "%X\n", ptr[i]);
+
+ vkUnmapMemory(device, staging.memory);
+
+ // Now destroy the staging buffer
+ vkDestroyBuffer(device, staging.buffer, nullptr);
+ vkFreeMemory(device, staging.memory, nullptr);
+ }
+ else
+ {
+ printf("invalid output type at %d.\n", id);
}
- id++;
}
- fclose(f);
-
-
+ id++;
}
+ fclose(f);
+}
- virtual void dispatchCompute(int x, int y, int z) override
- {
-
-
- // HACK: create a new pipeline for every call
+void VKRenderer::dispatchCompute(int x, int y, int z)
+{
+ // HACK: create a new pipeline for every call
- // First create a pipeline layout based on what is bound
+ // First create a pipeline layout based on what is bound
- Slang::List<VkDescriptorSetLayoutBinding> bindings;
+ Slang::List<VkDescriptorSetLayoutBinding> bindings;
- for( auto bb : currentBindingState->bindings )
+ for (auto bb : currentBindingState->bindings)
+ {
+ switch (bb.type)
{
- switch( bb.type )
- {
case ShaderInputType::Buffer:
+ {
+ switch (bb.bufferType)
{
- switch(bb.bufferType)
- {
case InputBufferType::StorageBuffer:
- {
- VkDescriptorSetLayoutBinding binding = {};
- binding.binding = bb.binding;
- binding.descriptorCount = 1;
- binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- binding.stageFlags = VK_SHADER_STAGE_ALL;
-
- bindings.Add(binding);
- }
- break;
+ {
+ VkDescriptorSetLayoutBinding binding = {};
+ binding.binding = bb.binding;
+ binding.descriptorCount = 1;
+ binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ binding.stageFlags = VK_SHADER_STAGE_ALL;
+
+ bindings.Add(binding);
+ }
+ break;
default:
// handle other cases
break;
- }
}
- break;
+ }
+ break;
default:
// TODO: handle the other cases
break;
- }
}
+ }
- VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
- descriptorSetLayoutInfo.bindingCount = uint32_t(bindings.Count());
- descriptorSetLayoutInfo.pBindings = bindings.Buffer();
+ VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
+ descriptorSetLayoutInfo.bindingCount = uint32_t(bindings.Count());
+ descriptorSetLayoutInfo.pBindings = bindings.Buffer();
- VkDescriptorSetLayout descriptorSetLayout = 0;
- checkResult(vkCreateDescriptorSetLayout(
- device, &descriptorSetLayoutInfo, nullptr, &descriptorSetLayout));
+ VkDescriptorSetLayout descriptorSetLayout = 0;
+ checkResult(vkCreateDescriptorSetLayout(
+ device, &descriptorSetLayoutInfo, nullptr, &descriptorSetLayout));
- // Create a descriptor pool for allocating sets
+ // Create a descriptor pool for allocating sets
- VkDescriptorPoolSize poolSizes[] =
- {
- { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 128 },
- { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 128 },
- { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 128 },
- };
+ VkDescriptorPoolSize poolSizes[] =
+ {
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 128 },
+ { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 128 },
+ { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 128 },
+ };
- VkDescriptorPoolCreateInfo descriptorPoolInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
- descriptorPoolInfo.maxSets = 128; // TODO: actually pick a size
- descriptorPoolInfo.poolSizeCount = sizeof(poolSizes) / sizeof(poolSizes[0]);
- descriptorPoolInfo.pPoolSizes = poolSizes;
+ VkDescriptorPoolCreateInfo descriptorPoolInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
+ descriptorPoolInfo.maxSets = 128; // TODO: actually pick a size
+ descriptorPoolInfo.poolSizeCount = sizeof(poolSizes) / sizeof(poolSizes[0]);
+ descriptorPoolInfo.pPoolSizes = poolSizes;
- VkDescriptorPool descriptorPool;
- checkResult(vkCreateDescriptorPool(
- device, &descriptorPoolInfo, nullptr, &descriptorPool));
+ VkDescriptorPool descriptorPool;
+ checkResult(vkCreateDescriptorPool(
+ device, &descriptorPoolInfo, nullptr, &descriptorPool));
- // Create a descriptor set based on our layout
+ // Create a descriptor set based on our layout
- VkDescriptorSetAllocateInfo descriptorSetAllocInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
- descriptorSetAllocInfo.descriptorPool = descriptorPool;
- descriptorSetAllocInfo.descriptorSetCount = 1;
- descriptorSetAllocInfo.pSetLayouts = &descriptorSetLayout;
+ VkDescriptorSetAllocateInfo descriptorSetAllocInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
+ descriptorSetAllocInfo.descriptorPool = descriptorPool;
+ descriptorSetAllocInfo.descriptorSetCount = 1;
+ descriptorSetAllocInfo.pSetLayouts = &descriptorSetLayout;
- VkDescriptorSet descriptorSet;
- checkResult(vkAllocateDescriptorSets(
- device, &descriptorSetAllocInfo, &descriptorSet));
+ VkDescriptorSet descriptorSet;
+ checkResult(vkAllocateDescriptorSets(
+ device, &descriptorSetAllocInfo, &descriptorSet));
- // Fill in the descritpor set, using our binding information
- for( auto bb : currentBindingState->bindings )
+ // Fill in the descritpor set, using our binding information
+ for (auto bb : currentBindingState->bindings)
+ {
+ switch (bb.type)
{
- switch( bb.type )
- {
case ShaderInputType::Buffer:
+ {
+ switch (bb.bufferType)
{
- switch(bb.bufferType)
- {
case InputBufferType::StorageBuffer:
- {
- VkDescriptorBufferInfo bufferInfo;
- bufferInfo.buffer = bb.buffer;
- bufferInfo.offset = 0;
- bufferInfo.range = bb.bufferLength;
-
- VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.descriptorCount = 1;
- writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- writeInfo.dstSet = descriptorSet;
- writeInfo.dstBinding = bb.binding;
- writeInfo.dstArrayElement = 0;
- writeInfo.pBufferInfo = &bufferInfo;
-
- vkUpdateDescriptorSets(
- device,
- 1,
- &writeInfo,
- 0,
- nullptr);
- }
- break;
+ {
+ VkDescriptorBufferInfo bufferInfo;
+ bufferInfo.buffer = bb.buffer;
+ bufferInfo.offset = 0;
+ bufferInfo.range = bb.bufferLength;
+
+ VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
+ writeInfo.descriptorCount = 1;
+ writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ writeInfo.dstSet = descriptorSet;
+ writeInfo.dstBinding = bb.binding;
+ writeInfo.dstArrayElement = 0;
+ writeInfo.pBufferInfo = &bufferInfo;
+
+ vkUpdateDescriptorSets(
+ device,
+ 1,
+ &writeInfo,
+ 0,
+ nullptr);
+ }
+ break;
default:
// handle other cases
break;
- }
}
- break;
+ }
+ break;
default:
// TODO: handle the other cases
break;
- }
}
+ }
- // Create a pipeline layout based on our descriptor set layout(s)
+ // Create a pipeline layout based on our descriptor set layout(s)
- VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
- pipelineLayoutInfo.setLayoutCount = 1;
- pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
+ pipelineLayoutInfo.setLayoutCount = 1;
+ pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
- VkPipelineLayout pipelineLayout = 0;
- checkResult(vkCreatePipelineLayout(
- device, &pipelineLayoutInfo, nullptr, &pipelineLayout));
+ VkPipelineLayout pipelineLayout = 0;
+ checkResult(vkCreatePipelineLayout(
+ device, &pipelineLayoutInfo, nullptr, &pipelineLayout));
- // Then create a pipeline to use that layout
+ // Then create a pipeline to use that layout
- VkComputePipelineCreateInfo computePipelineInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
- computePipelineInfo.stage = currentProgram->compute;
- computePipelineInfo.layout = pipelineLayout;
+ VkComputePipelineCreateInfo computePipelineInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
+ computePipelineInfo.stage = currentProgram->compute;
+ computePipelineInfo.layout = pipelineLayout;
- VkPipelineCache pipelineCache = 0;
+ VkPipelineCache pipelineCache = 0;
- VkPipeline pipeline;
- checkResult(vkCreateComputePipelines(
- device, pipelineCache, 1, &computePipelineInfo, nullptr, &pipeline));
+ VkPipeline pipeline;
+ checkResult(vkCreateComputePipelines(
+ device, pipelineCache, 1, &computePipelineInfo, nullptr, &pipeline));
- // Also create descriptor sets based on the given pipeline layout
+ // Also create descriptor sets based on the given pipeline layout
- VkCommandBuffer commandBuffer = beginCommandBuffer();
+ VkCommandBuffer commandBuffer = beginCommandBuffer();
- vkCmdBindPipeline(
- commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
+ vkCmdBindPipeline(
+ commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
- vkCmdBindDescriptorSets(
- commandBuffer,
- VK_PIPELINE_BIND_POINT_COMPUTE,
- pipelineLayout,
- 0, 1,
- &descriptorSet,
- 0,
- nullptr);
+ vkCmdBindDescriptorSets(
+ commandBuffer,
+ VK_PIPELINE_BIND_POINT_COMPUTE,
+ pipelineLayout,
+ 0, 1,
+ &descriptorSet,
+ 0,
+ nullptr);
- vkCmdDispatch(commandBuffer, x, y, z);
+ vkCmdDispatch(commandBuffer, x, y, z);
- flushCommandBuffer(commandBuffer);
+ flushCommandBuffer(commandBuffer);
- vkDestroyPipeline(device, pipeline, nullptr);
+ vkDestroyPipeline(device, pipeline, nullptr);
- // TODO: need to free up the other resources too...
- }
+ // TODO: need to free up the other resources too...
+}
- // ShaderCompiler interface
- VkPipelineShaderStageCreateInfo compileEntryPoint(
- ShaderCompileRequest::EntryPoint const& entryPointRequest,
- VkShaderStageFlagBits stage)
+
+// ShaderCompiler interface
+ShaderProgram* VKRenderer::compileProgram(const ShaderCompileRequest & request)
+{
+ ShaderProgramImpl* impl = new ShaderProgramImpl;
+ if (request.computeShader.name)
{
- char const* dataBegin = entryPointRequest.source.dataBegin;
- char const* dataEnd = entryPointRequest.source.dataEnd;
-
- // We need to make a copy of the code, since the Slang compiler
- // will free the memory after a compile request is closed.
- size_t codeSize = dataEnd - dataBegin;
- char* codeBegin = (char*) malloc(codeSize);
- memcpy(codeBegin, dataBegin, codeSize);
-
- VkShaderModuleCreateInfo moduleCreateInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
- moduleCreateInfo.pCode = (uint32_t*) codeBegin;
- moduleCreateInfo.codeSize = codeSize;
-
- VkShaderModule module;
- checkResult(vkCreateShaderModule(
- device,
- &moduleCreateInfo,
- nullptr,
- &module));
-
- VkPipelineShaderStageCreateInfo shaderStageCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
- shaderStageCreateInfo.stage = stage;
-
- shaderStageCreateInfo.module = module;
- shaderStageCreateInfo.pName = "main";
- return shaderStageCreateInfo;
+ impl->compute = compileEntryPoint(request.computeShader, VK_SHADER_STAGE_COMPUTE_BIT);
}
-
- virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override
+ else
{
- ShaderProgramImpl* impl = new ShaderProgramImpl();
-
- if( request.computeShader.name )
- {
- impl->compute = compileEntryPoint(
- request.computeShader,
- VK_SHADER_STAGE_COMPUTE_BIT);
- }
- else
- {
- impl->vertex = compileEntryPoint(
- request.vertexShader,
- VK_SHADER_STAGE_VERTEX_BIT);
-
- impl->fragment = compileEntryPoint(
- request.fragmentShader,
- VK_SHADER_STAGE_FRAGMENT_BIT);
- }
-
- return (ShaderProgram*) impl;
+ impl->vertex = compileEntryPoint(request.vertexShader, VK_SHADER_STAGE_VERTEX_BIT);
+ impl->fragment = compileEntryPoint(request.fragmentShader, VK_SHADER_STAGE_FRAGMENT_BIT);
}
-};
-
-
-
-Renderer* createVKRenderer()
-{
- return new VKRenderer();
+ return (ShaderProgram*)impl;
}
+
} // renderer_test