summaryrefslogtreecommitdiff
path: root/tools/render-test/render-vk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/render-test/render-vk.cpp')
-rw-r--r--tools/render-test/render-vk.cpp2019
1 files changed, 0 insertions, 2019 deletions
diff --git a/tools/render-test/render-vk.cpp b/tools/render-test/render-vk.cpp
deleted file mode 100644
index bbdc2f08c..000000000
--- a/tools/render-test/render-vk.cpp
+++ /dev/null
@@ -1,2019 +0,0 @@
-// render-vk.cpp
-#include "render-vk.h"
-
-#include "options.h"
-#include "render.h"
-
-#include "../../source/core/smart-pointer.h"
-
-#include "vk-api.h"
-#include "vk-util.h"
-#include "vk-device-queue.h"
-#include "vk-swap-chain.h"
-
-#include "surface.h"
-
-// Vulkan has a different coordinate system to ogl
-// http://anki3d.org/vulkan-coordinate-system/
-
-#define ENABLE_VALIDATION_LAYER 1
-
-#ifdef _MSC_VER
-# include <stddef.h>
-# pragma warning(disable: 4996)
-# if (_MSC_VER < 1900)
-# define snprintf sprintf_s
-# endif
-#endif
-
-namespace renderer_test {
-using namespace Slang;
-
-class VKRenderer : public Renderer
-{
-public:
- enum { kMaxRenderTargets = 8, kMaxAttachments = kMaxRenderTargets + 1 };
-
- // Renderer implementation
- virtual SlangResult initialize(const Desc& desc, void* inWindowHandle) override;
- virtual void setClearColor(const float color[4]) override;
- virtual void clearFrame() override;
- virtual void presentFrame() override;
- virtual TextureResource* createTextureResource(Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData) override;
- virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& bufferDesc, const void* initData) override;
- virtual SlangResult captureScreenSurface(Surface& surface) override;
- virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) override;
- virtual BindingState* createBindingState(const BindingState::Desc& bindingStateDesc) override;
- virtual ShaderProgram* createProgram(const ShaderProgram::Desc& desc) override;
- virtual void* map(BufferResource* buffer, MapFlavor flavor) override;
- virtual void unmap(BufferResource* 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, BufferResource*const* buffers, const UInt* strides, const UInt* offsets) override;
- virtual void setShaderProgram(ShaderProgram* inProgram) override;
- virtual void draw(UInt vertexCount, UInt startVertex) override;
- virtual void dispatchCompute(int x, int y, int z) override;
- virtual void submitGpuWork() override;
- virtual void waitForGpu() override;
- virtual RendererType getRendererType() const override { return RendererType::Vulkan; }
-
- /// Dtor
- ~VKRenderer();
-
- protected:
-
- class Buffer
- {
- public:
- /// Initialize a buffer with specified size, and memory props
- Result init(const VulkanApi& api, size_t bufferSize, VkBufferUsageFlags usage, VkMemoryPropertyFlags reqMemoryProperties);
-
- /// Returns true if has been initialized
- bool isInitialized() const { return m_api != nullptr; }
-
- // Default Ctor
- Buffer():
- m_api(nullptr)
- {}
-
- /// Dtor
- ~Buffer()
- {
- if (m_api)
- {
- m_api->vkDestroyBuffer(m_api->m_device, m_buffer, nullptr);
- m_api->vkFreeMemory(m_api->m_device, m_memory, nullptr);
- }
- }
-
- VkBuffer m_buffer;
- VkDeviceMemory m_memory;
- const VulkanApi* m_api;
- };
-
- class InputLayoutImpl : public InputLayout
- {
- public:
- List<VkVertexInputAttributeDescription> m_vertexDescs;
- int m_vertexSize;
- };
-
- class BufferResourceImpl: public BufferResource
- {
- public:
- typedef BufferResource Parent;
-
- BufferResourceImpl(Resource::Usage initialUsage, const BufferResource::Desc& desc, VKRenderer* renderer):
- Parent(desc),
- m_renderer(renderer),
- m_initialUsage(initialUsage)
- {
- assert(renderer);
- }
-
- Resource::Usage m_initialUsage;
- VKRenderer* m_renderer;
- Buffer m_buffer;
- Buffer m_uploadBuffer;
- List<uint8_t> m_readBuffer; ///< Stores the contents when a map read is performed
-
- MapFlavor m_mapFlavor = MapFlavor::Unknown; ///< If resource is mapped, records what kind of mapping else Unknown (if not mapped)
- };
-
- class TextureResourceImpl : public TextureResource
- {
- public:
- typedef TextureResource Parent;
-
- TextureResourceImpl(const Desc& desc, Usage initialUsage, const VulkanApi* api) :
- Parent(desc),
- m_initialUsage(initialUsage),
- m_api(api)
- {
- }
- ~TextureResourceImpl()
- {
- if (m_api)
- {
- if (m_imageMemory != VK_NULL_HANDLE)
- {
- m_api->vkFreeMemory(m_api->m_device, m_imageMemory, nullptr);
- }
- if (m_image != VK_NULL_HANDLE)
- {
- m_api->vkDestroyImage(m_api->m_device, m_image, nullptr);
- }
- }
- }
-
- Usage m_initialUsage;
-
- VkImage m_image = VK_NULL_HANDLE;
- VkDeviceMemory m_imageMemory = VK_NULL_HANDLE;
-
- const VulkanApi* m_api;
- };
-
- class ShaderProgramImpl: public ShaderProgram
- {
- public:
-
- ShaderProgramImpl(PipelineType pipelineType):
- m_pipelineType(pipelineType)
- {}
-
- PipelineType m_pipelineType;
-
- VkPipelineShaderStageCreateInfo m_compute;
- VkPipelineShaderStageCreateInfo m_vertex;
- VkPipelineShaderStageCreateInfo m_fragment;
-
- List<char> m_buffers[2]; //< To keep storage of code in scope
- };
-
- struct BindingDetail
- {
- VkImageView m_srv = VK_NULL_HANDLE;
- VkBufferView m_uav = VK_NULL_HANDLE;
- VkSampler m_sampler = VK_NULL_HANDLE;
- };
-
- class BindingStateImpl: public BindingState
- {
- public:
- typedef BindingState Parent;
-
- BindingStateImpl(const Desc& desc, const VulkanApi* api):
- Parent(desc),
- m_api(api)
- {
- }
- ~BindingStateImpl()
- {
- for (int i = 0; i < int(m_bindingDetails.Count()); ++i)
- {
- BindingDetail& detail = m_bindingDetails[i];
- if (detail.m_sampler != VK_NULL_HANDLE)
- {
- m_api->vkDestroySampler(m_api->m_device, detail.m_sampler, nullptr);
- }
- if (detail.m_srv != VK_NULL_HANDLE)
- {
- m_api->vkDestroyImageView(m_api->m_device, detail.m_srv, nullptr);
- }
- if (detail.m_uav != VK_NULL_HANDLE)
- {
- m_api->vkDestroyBufferView(m_api->m_device, detail.m_uav, nullptr);
- }
- }
- }
-
- const VulkanApi* m_api;
- List<BindingDetail> m_bindingDetails;
- };
-
- struct BoundVertexBuffer
- {
- RefPtr<BufferResourceImpl> m_buffer;
- int m_stride;
- int m_offset;
- };
-
- class Pipeline : public RefObject
- {
- public:
- Pipeline(const VulkanApi& api):
- m_api(&api)
- {
- }
- ~Pipeline()
- {
- if (m_pipeline != VK_NULL_HANDLE)
- {
- m_api->vkDestroyPipeline(m_api->m_device, m_pipeline, nullptr);
- }
- if (m_descriptorPool != VK_NULL_HANDLE)
- {
- m_api->vkDestroyDescriptorPool(m_api->m_device, m_descriptorPool, nullptr);
- }
- if (m_pipelineLayout != VK_NULL_HANDLE)
- {
- m_api->vkDestroyPipelineLayout(m_api->m_device, m_pipelineLayout, nullptr);
- }
- if(m_descriptorSetLayout != VK_NULL_HANDLE)
- {
- m_api->vkDestroyDescriptorSetLayout(m_api->m_device, m_descriptorSetLayout, nullptr);
- }
- }
-
- const VulkanApi* m_api;
-
- VkPrimitiveTopology m_primitiveTopology;
- RefPtr<BindingStateImpl> m_bindingState;
- RefPtr<InputLayoutImpl> m_inputLayout;
- RefPtr<ShaderProgramImpl> m_shaderProgram;
-
- VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE;
- VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
- VkDescriptorPool m_descriptorPool = VK_NULL_HANDLE;
- VkDescriptorSet m_descriptorSet = VK_NULL_HANDLE;
- VkPipeline m_pipeline = VK_NULL_HANDLE;
- };
-
- VkBool32 handleDebugMessage(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
- size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg);
-
- VkPipelineShaderStageCreateInfo compileEntryPoint(
- ShaderProgram::KernelDesc const& kernelDesc,
- VkShaderStageFlagBits stage,
- List<char>& bufferOut);
-
- 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);
-
- /// Returns true if m_currentPipeline matches the current configuration
- Pipeline* _getPipeline();
- bool _isEqual(const Pipeline& pipeline) const;
- Slang::Result _createPipeline(RefPtr<Pipeline>& pipelineOut);
- void _beginRender();
- void _endRender();
-
- Slang::Result _beginPass();
- void _endPass();
- void _transitionImageLayout(VkImage image, VkFormat format, const TextureResource::Desc& desc, VkImageLayout oldLayout, VkImageLayout newLayout);
-
- VkDebugReportCallbackEXT m_debugReportCallback;
-
- RefPtr<InputLayoutImpl> m_currentInputLayout;
- RefPtr<BindingStateImpl> m_currentBindingState;
- RefPtr<ShaderProgramImpl> m_currentProgram;
-
- List<RefPtr<Pipeline> > m_pipelineCache;
- Pipeline* m_currentPipeline = nullptr;
-
- List<BoundVertexBuffer> m_boundVertexBuffers;
-
- VkPrimitiveTopology m_primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
-
- VkDevice m_device = VK_NULL_HANDLE;
-
- VulkanModule m_module;
- VulkanApi m_api;
-
- VulkanDeviceQueue m_deviceQueue;
- VulkanSwapChain m_swapChain;
-
- VkRenderPass m_renderPass = VK_NULL_HANDLE;
-
- int m_swapChainImageIndex = -1;
-
- float m_clearColor[4] = { 0, 0, 0, 0 };
-
- Desc m_desc;
-};
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! VkRenderer::Buffer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-Result VKRenderer::Buffer::init(const VulkanApi& api, size_t bufferSize, VkBufferUsageFlags usage, VkMemoryPropertyFlags reqMemoryProperties)
-{
- assert(!isInitialized());
-
- m_api = &api;
- m_memory = VK_NULL_HANDLE;
- m_buffer = VK_NULL_HANDLE;
-
- VkBufferCreateInfo bufferCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
- bufferCreateInfo.size = bufferSize;
- bufferCreateInfo.usage = usage;
-
- SLANG_VK_CHECK(api.vkCreateBuffer(api.m_device, &bufferCreateInfo, nullptr, &m_buffer));
-
- VkMemoryRequirements memoryReqs = {};
- api.vkGetBufferMemoryRequirements(api.m_device, m_buffer, &memoryReqs);
-
- int memoryTypeIndex = api.findMemoryTypeIndex(memoryReqs.memoryTypeBits, reqMemoryProperties);
- assert(memoryTypeIndex >= 0);
-
- VkMemoryPropertyFlags actualMemoryProperites = api.m_deviceMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags;
-
- VkMemoryAllocateInfo allocateInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
- allocateInfo.allocationSize = memoryReqs.size;
- allocateInfo.memoryTypeIndex = memoryTypeIndex;
-
- SLANG_VK_CHECK(api.vkAllocateMemory(api.m_device, &allocateInfo, nullptr, &m_memory));
- SLANG_VK_CHECK(api.vkBindBufferMemory(api.m_device, m_buffer, m_memory, 0));
-
- return SLANG_OK;
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! VkRenderer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-bool VKRenderer::_isEqual(const Pipeline& pipeline) const
-{
- return
- pipeline.m_bindingState == m_currentBindingState &&
- pipeline.m_primitiveTopology == m_primitiveTopology &&
- pipeline.m_inputLayout == m_currentInputLayout &&
- pipeline.m_shaderProgram == m_currentProgram;
-}
-
-VKRenderer::Pipeline* VKRenderer::_getPipeline()
-{
- if (m_currentPipeline && _isEqual(*m_currentPipeline))
- {
- return m_currentPipeline;
- }
-
- // Look for a match in the cache
- for (int i = 0; i < int(m_pipelineCache.Count()); ++i)
- {
- Pipeline* pipeline = m_pipelineCache[i];
- if (_isEqual(*pipeline))
- {
- m_currentPipeline = pipeline;
- return pipeline;
- }
- }
-
- RefPtr<Pipeline> pipeline;
- SLANG_RETURN_NULL_ON_FAIL(_createPipeline(pipeline));
- m_pipelineCache.Add(pipeline);
- m_currentPipeline = pipeline;
- return pipeline;
-}
-
-Slang::Result VKRenderer::_createPipeline(RefPtr<Pipeline>& pipelineOut)
-{
- RefPtr<Pipeline> pipeline(new Pipeline(m_api));
-
- // Initialize the state
- pipeline->m_primitiveTopology = m_primitiveTopology;
- pipeline->m_bindingState = m_currentBindingState;
- pipeline->m_shaderProgram = m_currentProgram;
- pipeline->m_inputLayout = m_currentInputLayout;
-
- // Must be equal at this point if all the items are correctly set in pipeline
- assert(_isEqual(*pipeline));
-
- // First create a pipeline layout based on what is bound
-
- const auto& srcDetails = m_currentBindingState->m_bindingDetails;
- const auto& srcBindings = m_currentBindingState->getDesc().m_bindings;
-
- const int numBindings = int(srcBindings.Count());
-
- int numBuffers = 0;
- int numImages = 0;
-
- int numDescriptorByType[VK_DESCRIPTOR_TYPE_RANGE_SIZE] = { 0, };
-
- Slang::List<VkDescriptorSetLayoutBinding> dstBindings;
- for (int i = 0; i < numBindings; ++i)
- {
- const auto& srcDetail = srcDetails[i];
- const auto& srcBinding = srcBindings[i];
-
- VkDescriptorSetLayoutBinding dstBinding = {};
-
- dstBinding.descriptorCount = 1;
-
- switch (srcBinding.bindingType)
- {
- case BindingType::Buffer:
- {
- BufferResourceImpl* bufferResource = static_cast<BufferResourceImpl*>(srcBinding.resource.Ptr());
- const BufferResource::Desc& bufferResourceDesc = bufferResource->getDesc();
-
- if (bufferResourceDesc.bindFlags & Resource::BindFlag::UnorderedAccess)
- {
- dstBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- dstBinding.stageFlags = VK_SHADER_STAGE_ALL;
- dstBindings.Add(dstBinding);
-
- numDescriptorByType[dstBinding.descriptorType] ++;
- numBuffers++;
- }
- else if (bufferResourceDesc.bindFlags & Resource::BindFlag::ConstantBuffer)
- {
- dstBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
- dstBinding.stageFlags = VK_SHADER_STAGE_ALL;
- dstBindings.Add(dstBinding);
-
- numDescriptorByType[dstBinding.descriptorType] ++;
- numBuffers++;
- }
- break;
- }
- case BindingType::Texture:
- {
- dstBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
- dstBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
- dstBindings.Add(dstBinding);
-
- numDescriptorByType[dstBinding.descriptorType] ++;
- numImages++;
- break;
- }
- case BindingType::Sampler:
- {
- dstBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
- dstBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
- dstBindings.Add(dstBinding);
-
- numDescriptorByType[dstBinding.descriptorType] ++;
- numImages++;
- break;
- }
-
- case BindingType::CombinedTextureSampler:
- {
- dstBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- dstBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
- dstBindings.Add(dstBinding);
-
- numDescriptorByType[dstBinding.descriptorType] ++;
- numImages++;
- break;
- }
- default:
- {
- assert(!"Unhandled type");
- return SLANG_FAIL;
- }
- }
- }
-
- // Create a descriptor pool for allocating sets
- {
-#if 0
- VkDescriptorPoolSize poolSizes[] =
- {
- { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 128 },
- { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 128 },
- { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 128 },
- };
-#endif
-
- List<VkDescriptorPoolSize> poolSizes;
- for (int i = 0; i < SLANG_COUNT_OF(numDescriptorByType); ++i)
- {
- int numDescriptors = numDescriptorByType[i];
- if (numDescriptors > 0)
- {
- const VkDescriptorPoolSize poolSize = { VkDescriptorType(i), uint32_t(numDescriptors) };
- poolSizes.Add(poolSize);
- }
- }
- VkDescriptorPoolCreateInfo descriptorPoolInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
-
- descriptorPoolInfo.maxSets = 128; // TODO: actually pick a size.
- descriptorPoolInfo.poolSizeCount = uint32_t(poolSizes.Count());
- descriptorPoolInfo.pPoolSizes = poolSizes.Buffer();
-
- SLANG_VK_CHECK(m_api.vkCreateDescriptorPool(m_device, &descriptorPoolInfo, nullptr, &pipeline->m_descriptorPool));
- }
-
- // Create the layout
- {
- VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
- descriptorSetLayoutInfo.bindingCount = uint32_t(dstBindings.Count());
- descriptorSetLayoutInfo.pBindings = dstBindings.Buffer();
-
- SLANG_VK_CHECK(m_api.vkCreateDescriptorSetLayout(m_device, &descriptorSetLayoutInfo, nullptr, &pipeline->m_descriptorSetLayout));
- }
-
- // Create a descriptor set based on our layout
- {
- VkDescriptorSetAllocateInfo descriptorSetAllocInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
- descriptorSetAllocInfo.descriptorPool = pipeline->m_descriptorPool;
- descriptorSetAllocInfo.descriptorSetCount = 1;
- descriptorSetAllocInfo.pSetLayouts = &pipeline->m_descriptorSetLayout;
-
- SLANG_VK_CHECK(m_api.vkAllocateDescriptorSets(m_device, &descriptorSetAllocInfo, &pipeline->m_descriptorSet));
- }
-
- // Fill in the descriptor set, using our binding information
-
- List<VkDescriptorImageInfo> imageInfos;
- List<VkDescriptorBufferInfo> bufferInfos;
- List<VkWriteDescriptorSet> writes;
-
- // Make sure there is enough space...
- imageInfos.Reserve(numImages);
- bufferInfos.Reserve(numBuffers);
-
- int elementIndex = 0;
-
- for (int i = 0; i < numBindings; ++i)
- {
- const auto& srcDetail = srcDetails[i];
- const auto& srcBinding = srcBindings[i];
-
- const int bindingIndex = srcBinding.registerRange.getSingleIndex();
-
- VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.descriptorCount = 1;
- writeInfo.dstSet = pipeline->m_descriptorSet;
- writeInfo.dstBinding = bindingIndex;
- writeInfo.dstArrayElement = 0;
-
- switch (srcBinding.bindingType)
- {
- case BindingType::Buffer:
- {
- assert(srcBinding.resource && srcBinding.resource->isBuffer());
- BufferResourceImpl* bufferResource = static_cast<BufferResourceImpl*>(srcBinding.resource.Ptr());
- const BufferResource::Desc& bufferResourceDesc = bufferResource->getDesc();
-
- {
- VkDescriptorBufferInfo bufferInfo;
- bufferInfo.buffer = bufferResource->m_buffer.m_buffer;
- bufferInfo.offset = 0;
- bufferInfo.range = bufferResourceDesc.sizeInBytes;
-
- bufferInfos.Add(bufferInfo);
- }
-
- writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- if (bufferResource->m_initialUsage == Resource::Usage::UnorderedAccess)
- {
- writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- }
- else if (bufferResource->m_initialUsage == Resource::Usage::ConstantBuffer)
- {
- writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
- }
-
- writeInfo.pBufferInfo = &bufferInfos.Last();
-
- writes.Add(writeInfo);
- break;
- }
- case BindingType::Texture:
- {
- assert(srcBinding.resource && srcBinding.resource->isTexture());
-
- TextureResourceImpl* textureResource = static_cast<TextureResourceImpl*>(srcBinding.resource.Ptr());
- const TextureResource::Desc& textureResourceDesc = textureResource->getDesc();
-
- {
- VkDescriptorImageInfo imageInfo = {};
- imageInfo.imageView = srcDetail.m_srv;
- imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- imageInfos.Add(imageInfo);
- }
-
- writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
- writeInfo.pImageInfo = &imageInfos.Last();
-
- writes.Add(writeInfo);
- break;
- }
- case BindingType::Sampler:
- {
- {
- VkDescriptorImageInfo imageInfo = {};
- imageInfo.sampler = srcDetail.m_sampler;
- //imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- imageInfos.Add(imageInfo);
- }
-
- writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
- writeInfo.pImageInfo = &imageInfos.Last();
-
- writes.Add(writeInfo);
- break;
- }
- default:
- {
- assert(!"Binding not currently handled");
- return SLANG_FAIL;
- }
- }
- }
-
- assert(imageInfos.Count() == numImages);
- assert(bufferInfos.Count() == numBuffers);
-
- // Write into the descriptor set
- {
- m_api.vkUpdateDescriptorSets(m_device, uint32_t(writes.Count()), writes.Buffer(), 0, nullptr);
- }
-
- // 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 = &pipeline->m_descriptorSetLayout;
-
- SLANG_VK_CHECK(m_api.vkCreatePipelineLayout(m_device, &pipelineLayoutInfo, nullptr, &pipeline->m_pipelineLayout));
-
- VkPipelineCache pipelineCache = VK_NULL_HANDLE;
-
- if (m_currentProgram->m_pipelineType == PipelineType::Compute)
- {
- // Then create a pipeline to use that layout
-
- VkComputePipelineCreateInfo computePipelineInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
- computePipelineInfo.stage = m_currentProgram->m_compute;
- computePipelineInfo.layout = pipeline->m_pipelineLayout;
-
- SLANG_VK_CHECK(m_api.vkCreateComputePipelines(m_device, pipelineCache, 1, &computePipelineInfo, nullptr, &pipeline->m_pipeline));
- }
- else if (m_currentProgram->m_pipelineType == PipelineType::Graphics)
- {
- // Create the graphics pipeline
-
- const int width = m_swapChain.getWidth();
- const int height = m_swapChain.getHeight();
-
- VkPipelineShaderStageCreateInfo shaderStages[] = { m_currentProgram->m_vertex, m_currentProgram->m_fragment };
-
- // VertexBuffer/s
- // Currently only handles one
-
- VkPipelineVertexInputStateCreateInfo vertexInputInfo = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
- vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
- vertexInputInfo.vertexBindingDescriptionCount = 0;
- vertexInputInfo.vertexAttributeDescriptionCount = 0;
-
- VkVertexInputBindingDescription vertexInputBindingDescription;
-
- if (m_currentInputLayout)
- {
- vertexInputBindingDescription.binding = 0;
- vertexInputBindingDescription.stride = m_currentInputLayout->m_vertexSize;
- vertexInputBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
-
- const auto& srcAttributeDescs = m_currentInputLayout->m_vertexDescs;
-
- vertexInputInfo.vertexBindingDescriptionCount = 1;
- vertexInputInfo.pVertexBindingDescriptions = &vertexInputBindingDescription;
-
- vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(srcAttributeDescs.Count());
- vertexInputInfo.pVertexAttributeDescriptions = srcAttributeDescs.Buffer();
- }
-
- //
-
- VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
- inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
- inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
- inputAssembly.primitiveRestartEnable = VK_FALSE;
-
- VkViewport viewport = {};
- viewport.x = 0.0f;
- viewport.y = 0.0f;
- viewport.width = (float)width;
- viewport.height = (float)height;
- viewport.minDepth = 0.0f;
- viewport.maxDepth = 1.0f;
-
- VkRect2D scissor = {};
- scissor.offset = { 0, 0 };
- scissor.extent = { uint32_t(width), uint32_t(height) };
-
- VkPipelineViewportStateCreateInfo viewportState = {};
- viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
- viewportState.viewportCount = 1;
- viewportState.pViewports = &viewport;
- viewportState.scissorCount = 1;
- viewportState.pScissors = &scissor;
-
- VkPipelineRasterizationStateCreateInfo rasterizer = {};
- rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
- rasterizer.depthClampEnable = VK_FALSE;
- rasterizer.rasterizerDiscardEnable = VK_FALSE;
- rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
- rasterizer.lineWidth = 1.0f;
- rasterizer.cullMode = VK_CULL_MODE_NONE;
- rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
- rasterizer.depthBiasEnable = VK_FALSE;
-
- VkPipelineMultisampleStateCreateInfo multisampling = {};
- multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
- multisampling.sampleShadingEnable = VK_FALSE;
- multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
-
- VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
- colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
- colorBlendAttachment.blendEnable = VK_FALSE;
-
- VkPipelineColorBlendStateCreateInfo colorBlending = {};
- colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
- colorBlending.logicOpEnable = VK_FALSE;
- colorBlending.logicOp = VK_LOGIC_OP_COPY;
- colorBlending.attachmentCount = 1;
- colorBlending.pAttachments = &colorBlendAttachment;
- colorBlending.blendConstants[0] = 0.0f;
- colorBlending.blendConstants[1] = 0.0f;
- colorBlending.blendConstants[2] = 0.0f;
- colorBlending.blendConstants[3] = 0.0f;
-
- VkGraphicsPipelineCreateInfo pipelineInfo = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
-
- pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
- pipelineInfo.stageCount = 2;
- pipelineInfo.pStages = shaderStages;
- pipelineInfo.pVertexInputState = &vertexInputInfo;
- pipelineInfo.pInputAssemblyState = &inputAssembly;
- pipelineInfo.pViewportState = &viewportState;
- pipelineInfo.pRasterizationState = &rasterizer;
- pipelineInfo.pMultisampleState = &multisampling;
- pipelineInfo.pColorBlendState = &colorBlending;
- pipelineInfo.layout = pipeline->m_pipelineLayout;
- pipelineInfo.renderPass = m_renderPass;
- pipelineInfo.subpass = 0;
- pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
-
- SLANG_VK_CHECK(m_api.vkCreateGraphicsPipelines(m_device, pipelineCache, 1, &pipelineInfo, nullptr, &pipeline->m_pipeline));
- }
- else
- {
- assert(!"Unhandled program type");
- return SLANG_FAIL;
- }
-
- pipelineOut = pipeline;
- return SLANG_OK;
-}
-
-Result VKRenderer::_beginPass()
-{
- if (m_swapChainImageIndex < 0)
- {
- return SLANG_FAIL;
- }
-
- const int numRenderTargets = 1;
-
- const VulkanSwapChain::Image& image = m_swapChain.getImages()[m_swapChainImageIndex];
-
- int numAttachments = 0;
-
- // Start render pass
- VkClearValue clearValues[kMaxAttachments];
- clearValues[numAttachments++] = VkClearValue{ m_clearColor[0], m_clearColor[1], m_clearColor[2], m_clearColor[3] };
-
- bool hasDepthBuffer = false;
- if (hasDepthBuffer)
- {
- VkClearValue& clearValue = clearValues[numAttachments++];
-
- clearValue.depthStencil.depth = 1.0f;
- clearValue.depthStencil.stencil = 0;
- }
-
- const int width = m_swapChain.getWidth();
- const int height = m_swapChain.getHeight();
-
- VkCommandBuffer cmdBuffer = m_deviceQueue.getCommandBuffer();
-
- VkRenderPassBeginInfo renderPassBegin = {};
- renderPassBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
- renderPassBegin.renderPass = m_renderPass;
- renderPassBegin.framebuffer = image.m_frameBuffer;
- renderPassBegin.renderArea.offset.x = 0;
- renderPassBegin.renderArea.offset.y = 0;
- renderPassBegin.renderArea.extent.width = width;
- renderPassBegin.renderArea.extent.height = height;
- renderPassBegin.clearValueCount = numAttachments;
- renderPassBegin.pClearValues = clearValues;
-
- m_api.vkCmdBeginRenderPass(cmdBuffer, &renderPassBegin, VK_SUBPASS_CONTENTS_INLINE);
-
- // Set up scissor and viewport
- {
- VkRect2D rects[kMaxRenderTargets] = {};
- VkViewport viewports[kMaxRenderTargets] = {};
- for (int i = 0; i < numRenderTargets; ++i)
- {
- rects[i] = VkRect2D{ 0, 0, uint32_t(width), uint32_t(height) };
-
- VkViewport& dstViewport = viewports[i];
-
- dstViewport.x = 0.0f;
- dstViewport.y = 0.0f;
- dstViewport.width = float(width);
- dstViewport.height = float(height);
- dstViewport.minDepth = 0.0f;
- dstViewport.maxDepth = 1.0f;
- }
-
- m_api.vkCmdSetScissor(cmdBuffer, 0, numRenderTargets, rects);
- m_api.vkCmdSetViewport(cmdBuffer, 0, numRenderTargets, viewports);
- }
-
- return SLANG_OK;
-}
-
-void VKRenderer::_endPass()
-{
- VkCommandBuffer cmdBuffer = m_deviceQueue.getCommandBuffer();
- m_api.vkCmdEndRenderPass(cmdBuffer);
-}
-
-void VKRenderer::_beginRender()
-{
- m_swapChainImageIndex = m_swapChain.nextFrontImageIndex();
-
- if (m_swapChainImageIndex < 0)
- {
- return;
- }
-}
-
-void VKRenderer::_endRender()
-{
- m_deviceQueue.flush();
-}
-
-Renderer* createVKRenderer()
-{
- return new VKRenderer;
-}
-
-VKRenderer::~VKRenderer()
-{
- if (m_renderPass != VK_NULL_HANDLE)
- {
- m_api.vkDestroyRenderPass(m_device, m_renderPass, nullptr);
- m_renderPass = VK_NULL_HANDLE;
- }
-}
-
-
-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";
-
- // pMsg can be really big (it can be assembler dump for example)
- // Use a dynamic buffer to store
- size_t bufferSize = strlen(pMsg) + 1 + 1024;
- List<char> bufferArray;
- bufferArray.SetSize(bufferSize);
- char* buffer = bufferArray.Buffer();
-
- sprintf_s(buffer,
- bufferSize,
- "%s: %s %d: %s\n",
- pLayerPrefix,
- severity,
- msgCode,
- pMsg);
-
- fprintf(stderr, "%s", buffer);
- fflush(stderr);
-
- OutputDebugStringA(buffer);
-
- return VK_FALSE;
-}
-
-/* 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);
-}
-
-VkPipelineShaderStageCreateInfo VKRenderer::compileEntryPoint(
- ShaderProgram::KernelDesc const& kernelDesc,
- VkShaderStageFlagBits stage,
- List<char>& bufferOut)
-{
- char const* dataBegin = (char const*) kernelDesc.codeBegin;
- char const* dataEnd = (char const*) kernelDesc.codeEnd;
-
- // 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;
-
- bufferOut.InsertRange(0, dataBegin, codeSize);
-
- char* codeBegin = bufferOut.Buffer();
-
- VkShaderModuleCreateInfo moduleCreateInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
- moduleCreateInfo.pCode = (uint32_t*)codeBegin;
- moduleCreateInfo.codeSize = codeSize;
-
- VkShaderModule module;
- SLANG_VK_CHECK(m_api.vkCreateShaderModule(m_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;
-}
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
-
-SlangResult VKRenderer::initialize(const Desc& desc, void* inWindowHandle)
-{
- SLANG_RETURN_ON_FAIL(m_module.init());
- SLANG_RETURN_ON_FAIL(m_api.initGlobalProcs(m_module));
-
- m_desc = desc;
-
- VkApplicationInfo applicationInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
- applicationInfo.pApplicationName = "slang-render-test";
- applicationInfo.pEngineName = "slang-render-test";
- applicationInfo.apiVersion = VK_API_VERSION_1_0;
-
- char const* instanceExtensions[] =
- {
- VK_KHR_SURFACE_EXTENSION_NAME,
-
-#if SLANG_WINDOWS_FAMILY
- VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
-#else
- VK_KHR_XLIB_SURFACE_EXTENSION_NAME
-#endif
-
-#if ENABLE_VALIDATION_LAYER
- VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
-#endif
- };
-
- VkInstance instance = VK_NULL_HANDLE;
-
- VkInstanceCreateInfo instanceCreateInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
- instanceCreateInfo.pApplicationInfo = &applicationInfo;
-
- instanceCreateInfo.enabledExtensionCount = SLANG_COUNT_OF(instanceExtensions);
- instanceCreateInfo.ppEnabledExtensionNames = &instanceExtensions[0];
-
-#if ENABLE_VALIDATION_LAYER
- const char* layerNames[] = { "VK_LAYER_LUNARG_standard_validation" };
- instanceCreateInfo.enabledLayerCount = SLANG_COUNT_OF(layerNames);
- instanceCreateInfo.ppEnabledLayerNames = layerNames;
-#endif
-
- SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
- SLANG_RETURN_ON_FAIL(m_api.initInstanceProcs(instance));
-
-#if ENABLE_VALIDATION_LAYER
- VkDebugReportFlagsEXT debugFlags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
-
- VkDebugReportCallbackCreateInfoEXT debugCreateInfo = { VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT };
- debugCreateInfo.pfnCallback = &debugMessageCallback;
- debugCreateInfo.pUserData = this;
- debugCreateInfo.flags = debugFlags;
-
- SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateDebugReportCallbackEXT(instance, &debugCreateInfo, nullptr, &m_debugReportCallback));
-#endif
-
- uint32_t numPhysicalDevices = 0;
- SLANG_VK_RETURN_ON_FAIL(m_api.vkEnumeratePhysicalDevices(instance, &numPhysicalDevices, nullptr));
-
- List<VkPhysicalDevice> physicalDevices;
- physicalDevices.SetSize(numPhysicalDevices);
- SLANG_VK_RETURN_ON_FAIL(m_api.vkEnumeratePhysicalDevices(instance, &numPhysicalDevices, physicalDevices.Buffer()));
-
- // TODO: allow override of selected device
- uint32_t selectedDeviceIndex = 0;
-
- SLANG_RETURN_ON_FAIL(m_api.initPhysicalDevice(physicalDevices[selectedDeviceIndex]));
-
- int queueFamilyIndex = m_api.findQueue(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
- assert(queueFamilyIndex >= 0);
-
- 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,
- };
-
- VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
- deviceCreateInfo.queueCreateInfoCount = 1;
- deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
- deviceCreateInfo.pEnabledFeatures = &m_api.m_deviceFeatures;
-
- deviceCreateInfo.enabledExtensionCount = SLANG_COUNT_OF(deviceExtensions);
- deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions;
-
- SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateDevice(m_api.m_physicalDevice, &deviceCreateInfo, nullptr, &m_device));
- SLANG_RETURN_ON_FAIL(m_api.initDeviceProcs(m_device));
-
- {
- VkQueue queue;
- m_api.vkGetDeviceQueue(m_device, queueFamilyIndex, 0, &queue);
- SLANG_RETURN_ON_FAIL(m_deviceQueue.init(m_api, queue, queueFamilyIndex));
- }
-
- // set up swap chain
-
- {
- VulkanSwapChain::Desc desc;
- VulkanSwapChain::PlatformDesc* platformDesc = nullptr;
-
- desc.init();
- desc.m_format = Format::RGBA_Unorm_UInt8;
-
-#if SLANG_WINDOWS_FAMILY
- VulkanSwapChain::WinPlatformDesc winPlatformDesc;
- winPlatformDesc.m_hinstance = ::GetModuleHandle(nullptr);
- winPlatformDesc.m_hwnd = (HWND)inWindowHandle;
- platformDesc = &winPlatformDesc;
-#endif
-
- SLANG_RETURN_ON_FAIL(m_swapChain.init(&m_deviceQueue, desc, platformDesc));
- }
-
- // depth/stencil?
-
- // render pass?
-
- {
- const int numRenderTargets = 1;
- bool shouldClear = true;
- bool shouldClearDepth = false;
- bool shouldClearStencil = false;
- bool hasDepthBuffer = false;
-
- Format depthFormat = Format::Unknown;
- VkFormat colorFormat = m_swapChain.getVkFormat();
-
- int numAttachments = 0;
- // We need extra space if we have depth buffer
- VkAttachmentDescription attachmentDesc[kMaxRenderTargets + 1] = {};
- for (int i = 0; i < numRenderTargets; ++i)
- {
- VkAttachmentDescription& dst = attachmentDesc[numAttachments ++];
-
- dst.flags = 0;
- dst.format = colorFormat;
- dst.samples = VK_SAMPLE_COUNT_1_BIT;
- dst.loadOp = shouldClear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
- dst.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- dst.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- dst.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- dst.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- dst.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- }
- if (hasDepthBuffer)
- {
- VkAttachmentDescription& dst = attachmentDesc[numAttachments++];
-
- dst.flags = 0;
- dst.format = VulkanUtil::getVkFormat(depthFormat);
- dst.samples = VK_SAMPLE_COUNT_1_BIT;
- dst.loadOp = shouldClearDepth ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
- dst.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- dst.stencilLoadOp = shouldClearStencil ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
- dst.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
- dst.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- dst.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- }
-
- VkAttachmentReference colorAttachments[kMaxRenderTargets] = {};
- for (int i = 0; i < numRenderTargets; ++i)
- {
- VkAttachmentReference& dst = colorAttachments[i];
- dst.attachment = i;
- dst.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- }
-
- VkAttachmentReference depthAttachment = {};
- depthAttachment.attachment = numRenderTargets;
- depthAttachment.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
-
- VkSubpassDescription subpassDesc = {};
- subpassDesc.flags = 0;
- subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpassDesc.inputAttachmentCount = 0u;
- subpassDesc.pInputAttachments = nullptr;
- subpassDesc.colorAttachmentCount = numRenderTargets;
- subpassDesc.pColorAttachments = colorAttachments;
- subpassDesc.pResolveAttachments = nullptr;
- subpassDesc.pDepthStencilAttachment = hasDepthBuffer ? &depthAttachment : nullptr;
- subpassDesc.preserveAttachmentCount = 0u;
- subpassDesc.pPreserveAttachments = nullptr;
-
- VkRenderPassCreateInfo renderPassCreateInfo = {};
- renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- renderPassCreateInfo.attachmentCount = numAttachments;
- renderPassCreateInfo.pAttachments = attachmentDesc;
- renderPassCreateInfo.subpassCount = 1;
- renderPassCreateInfo.pSubpasses = &subpassDesc;
- SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateRenderPass(m_device, &renderPassCreateInfo, nullptr, &m_renderPass));
- }
-
- // frame buffer
- SLANG_RETURN_ON_FAIL(m_swapChain.createFrameBuffers(m_renderPass));
-
- _beginRender();
-
- return SLANG_OK;
-}
-
-void VKRenderer::submitGpuWork()
-{
- m_deviceQueue.flush();
-}
-
-void VKRenderer::waitForGpu()
-{
- m_deviceQueue.flushAndWait();
-}
-
-void VKRenderer::setClearColor(const float color[4])
-{
- for (int ii = 0; ii < 4; ++ii)
- m_clearColor[ii] = color[ii];
-}
-
-void VKRenderer::clearFrame()
-{
-}
-
-void VKRenderer::presentFrame()
-{
- _endRender();
-
- const bool vsync = true;
- m_swapChain.present(vsync);
-
- _beginRender();
-}
-
-SlangResult VKRenderer::captureScreenSurface(Surface& surfaceOut)
-{
- return SLANG_FAIL;
-}
-
-static VkBufferUsageFlagBits _calcBufferUsageFlags(Resource::BindFlag::Enum bind)
-{
- typedef Resource::BindFlag BindFlag;
-
- switch (bind)
- {
- case BindFlag::VertexBuffer: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
- case BindFlag::IndexBuffer: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
- case BindFlag::ConstantBuffer: return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
- case BindFlag::StreamOutput:
- case BindFlag::RenderTarget:
- case BindFlag::DepthStencil:
- {
- assert(!"Not supported yet");
- return VkBufferUsageFlagBits(0);
- }
- case BindFlag::UnorderedAccess: return VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
- case BindFlag::PixelShaderResource: return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
- case BindFlag::NonPixelShaderResource: return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
- default: return VkBufferUsageFlagBits(0);
- }
-}
-
-static VkBufferUsageFlagBits _calcBufferUsageFlags(int bindFlags)
-{
- int dstFlags = 0;
- while (bindFlags)
- {
- int lsb = bindFlags & -bindFlags;
- dstFlags |= _calcBufferUsageFlags(Resource::BindFlag::Enum(lsb));
- bindFlags &= ~lsb;
- }
- return VkBufferUsageFlagBits(dstFlags);
-}
-
-static VkBufferUsageFlags _calcBufferUsageFlags(int bindFlags, int cpuAccessFlags, const void* initData)
-{
- VkBufferUsageFlags usage = _calcBufferUsageFlags(bindFlags);
-
- if (cpuAccessFlags & Resource::AccessFlag::Read)
- {
- // If it can be read from, set this
- usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- }
- if ((cpuAccessFlags & Resource::AccessFlag::Write) || initData)
- {
- usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- }
-
- return usage;
-}
-
-static VkImageUsageFlagBits _calcImageUsageFlags(Resource::BindFlag::Enum bind)
-{
- typedef Resource::BindFlag BindFlag;
-
- switch (bind)
- {
- case BindFlag::RenderTarget: return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
- case BindFlag::DepthStencil: return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
- case BindFlag::NonPixelShaderResource:
- case BindFlag::PixelShaderResource:
- {
- // Ignore
- return VkImageUsageFlagBits(0);
- }
- default:
- {
- assert(!"Unsupported");
- return VkImageUsageFlagBits(0);
- }
- }
-}
-
-static VkImageUsageFlagBits _calcImageUsageFlags(int bindFlags)
-{
- int dstFlags = 0;
- while (bindFlags)
- {
- int lsb = bindFlags & -bindFlags;
- dstFlags |= _calcImageUsageFlags(Resource::BindFlag::Enum(lsb));
- bindFlags &= ~lsb;
- }
- return VkImageUsageFlagBits(dstFlags);
-}
-
-static VkImageUsageFlags _calcImageUsageFlags(int bindFlags, int cpuAccessFlags, const void* initData)
-{
- VkImageUsageFlags usage = _calcImageUsageFlags(bindFlags);
-
- usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
-
- if (cpuAccessFlags & Resource::AccessFlag::Read)
- {
- // If it can be read from, set this
- usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
- }
- if ((cpuAccessFlags & Resource::AccessFlag::Write) || initData)
- {
- usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- }
-
- return usage;
-}
-
-void VKRenderer::_transitionImageLayout(VkImage image, VkFormat format, const TextureResource::Desc& desc, VkImageLayout oldLayout, VkImageLayout newLayout)
-{
- VkImageMemoryBarrier barrier = {};
- barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- barrier.oldLayout = oldLayout;
- barrier.newLayout = newLayout;
- barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.image = image;
- barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- barrier.subresourceRange.baseMipLevel = 0;
- barrier.subresourceRange.levelCount = desc.numMipLevels;
- barrier.subresourceRange.baseArrayLayer = 0;
- barrier.subresourceRange.layerCount = 1;
-
- VkPipelineStageFlags sourceStage;
- VkPipelineStageFlags destinationStage;
-
- if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
- {
- barrier.srcAccessMask = 0;
- barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
-
- sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
- destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
- }
- else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
- {
- barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
-
- sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
- destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- }
- else
- {
- assert(!"unsupported layout transition!");
- return;
- }
-
- VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer();
-
- m_api.vkCmdPipelineBarrier(commandBuffer, sourceStage, destinationStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
-}
-
-TextureResource* VKRenderer::createTextureResource(Resource::Usage initialUsage, const TextureResource::Desc& descIn, const TextureResource::Data* initData)
-{
- TextureResource::Desc desc(descIn);
- desc.setDefaults(initialUsage);
-
- const VkFormat format = VulkanUtil::getVkFormat(desc.format);
- if (format == VK_FORMAT_UNDEFINED)
- {
- assert(!"Unhandled image format");
- return nullptr;
- }
-
- const int arraySize = desc.calcEffectiveArraySize();
-
- RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(desc, initialUsage, &m_api));
-
- // Create the image
- {
- VkImageCreateInfo imageInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
-
- switch (desc.type)
- {
- case Resource::Type::Texture1D:
- {
- imageInfo.imageType = VK_IMAGE_TYPE_1D;
- imageInfo.extent = VkExtent3D{ uint32_t(descIn.size.width), 1, 1 };
- break;
- }
- case Resource::Type::Texture2D:
- {
- imageInfo.imageType = VK_IMAGE_TYPE_2D;
- imageInfo.extent = VkExtent3D{ uint32_t(descIn.size.width), uint32_t(descIn.size.height), 1 };
- break;
- }
- case Resource::Type::TextureCube:
- {
- imageInfo.imageType = VK_IMAGE_TYPE_2D;
- imageInfo.extent = VkExtent3D{ uint32_t(descIn.size.width), uint32_t(descIn.size.height), 1 };
- break;
- }
- case Resource::Type::Texture3D:
- {
- // Can't have an array and 3d texture
- assert(desc.arraySize <= 1);
-
- imageInfo.imageType = VK_IMAGE_TYPE_3D;
- imageInfo.extent = VkExtent3D{ uint32_t(descIn.size.width), uint32_t(descIn.size.height), uint32_t(descIn.size.depth) };
- break;
- }
- default:
- {
- assert(!"Unhandled type");
- return nullptr;
- }
- }
-
- imageInfo.mipLevels = desc.numMipLevels;
- imageInfo.arrayLayers = arraySize;
-
- imageInfo.format = format;
-
- imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
- imageInfo.usage = _calcImageUsageFlags(desc.bindFlags, desc.cpuAccessFlags, initData);
- imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
-
- imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
- imageInfo.flags = 0; // Optional
-
- SLANG_VK_RETURN_NULL_ON_FAIL(m_api.vkCreateImage(m_device, &imageInfo, nullptr, &texture->m_image));
- }
-
- VkMemoryRequirements memRequirements;
- m_api.vkGetImageMemoryRequirements(m_device, texture->m_image, &memRequirements);
-
- // Allocate the memory
- {
- VkMemoryPropertyFlags reqMemoryProperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
-
- VkMemoryAllocateInfo allocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
-
- int memoryTypeIndex = m_api.findMemoryTypeIndex(memRequirements.memoryTypeBits, reqMemoryProperties);
- assert(memoryTypeIndex >= 0);
-
- VkMemoryPropertyFlags actualMemoryProperites = m_api.m_deviceMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags;
-
- allocInfo.allocationSize = memRequirements.size;
- allocInfo.memoryTypeIndex = memoryTypeIndex;
-
- SLANG_VK_RETURN_NULL_ON_FAIL(m_api.vkAllocateMemory(m_device, &allocInfo, nullptr, &texture->m_imageMemory));
- }
-
- // Bind the memory to the image
- m_api.vkBindImageMemory(m_device, texture->m_image, texture->m_imageMemory, 0);
-
- if (initData)
- {
- List<TextureResource::Size> mipSizes;
-
- VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer();
-
- const int numMipMaps = desc.numMipLevels;
- assert(initData->numMips == numMipMaps);
-
- // Calculate how large the buffer has to be
- size_t bufferSize = 0;
- // Calculate how large an array entry is
- for (int j = 0; j < numMipMaps; ++j)
- {
- const TextureResource::Size mipSize = desc.size.calcMipSize(j);
-
- const int rowSizeInBytes = Surface::calcRowSize(desc.format, mipSize.width);
- const int numRows = Surface::calcNumRows(desc.format, mipSize.height);
-
- mipSizes.Add(mipSize);
-
- bufferSize += (rowSizeInBytes * numRows) * mipSize.depth;
- }
-
-
- // Calculate the total size taking into account the array
- bufferSize *= arraySize;
-
- Buffer uploadBuffer;
- SLANG_RETURN_NULL_ON_FAIL(uploadBuffer.init(m_api, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
-
- assert(mipSizes.Count() == numMipMaps);
-
- // Copy into upload buffer
- {
- int subResourceIndex = 0;
-
- uint8_t* dstData;
- m_api.vkMapMemory(m_device, uploadBuffer.m_memory, 0, bufferSize, 0, (void**)&dstData);
-
- for (int i = 0; i < arraySize; ++i)
- {
- for (int j = 0; j < int(mipSizes.Count()); ++j)
- {
- const auto& mipSize = mipSizes[j];
-
- const ptrdiff_t srcRowStride = initData->mipRowStrides[j];
- const int dstRowSizeInBytes = Surface::calcRowSize(desc.format, mipSize.width);
- const int numRows = Surface::calcNumRows(desc.format, mipSize.height);
-
- for (int k = 0; k < mipSize.depth; k++)
- {
- const uint8_t* srcData = (const uint8_t*)(initData->subResources[subResourceIndex]);
-
- for (int l = 0; l < numRows; l++)
- {
- ::memcpy(dstData, srcData, dstRowSizeInBytes);
-
- dstData += dstRowSizeInBytes;
- srcData += srcRowStride;
- }
-
- subResourceIndex++;
- }
- }
- }
-
- m_api.vkUnmapMemory(m_device, uploadBuffer.m_memory);
- }
-
- _transitionImageLayout(texture->m_image, format, texture->getDesc(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
-
- {
- size_t srcOffset = 0;
- for (int i = 0; i < arraySize; ++i)
- {
- for (int j = 0; j < int(mipSizes.Count()); ++j)
- {
- const auto& mipSize = mipSizes[j];
-
- const int rowSizeInBytes = Surface::calcRowSize(desc.format, mipSize.width);
- const int numRows = Surface::calcNumRows(desc.format, mipSize.height);
-
- // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkBufferImageCopy.html
- // bufferRowLength and bufferImageHeight specify the data in buffer memory as a subregion of a larger two- or three-dimensional image,
- // and control the addressing calculations of data in buffer memory. If either of these values is zero, that aspect of the buffer memory
- // is considered to be tightly packed according to the imageExtent.
-
- VkBufferImageCopy region = {};
-
- region.bufferOffset = srcOffset;
- region.bufferRowLength = 0; //rowSizeInBytes;
- region.bufferImageHeight = 0;
-
- region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- region.imageSubresource.mipLevel = j;
- region.imageSubresource.baseArrayLayer = i;
- region.imageSubresource.layerCount = 1;
- region.imageOffset = { 0, 0, 0 };
- region.imageExtent = { uint32_t(mipSize.width), uint32_t(mipSize.height), uint32_t(mipSize.depth) };
-
- // Do the copy (do all depths in a single go)
- m_api.vkCmdCopyBufferToImage(commandBuffer, uploadBuffer.m_buffer, texture->m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
-
- // Next
- srcOffset += rowSizeInBytes * numRows * mipSize.depth;
- }
- }
- }
-
- _transitionImageLayout(texture->m_image, format, texture->getDesc(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
-
- m_deviceQueue.flushAndWait();
- }
-
- return texture.detach();
-}
-
-BufferResource* VKRenderer::createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData)
-{
- BufferResource::Desc desc(descIn);
- desc.setDefaults(initialUsage);
-
- const size_t bufferSize = desc.sizeInBytes;
-
- VkMemoryPropertyFlags reqMemoryProperties = 0;
-
- VkBufferUsageFlags usage = _calcBufferUsageFlags(desc.bindFlags, desc.cpuAccessFlags, initData);
-
- switch (initialUsage)
- {
- case Resource::Usage::ConstantBuffer:
- {
- reqMemoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
- break;
- }
- default: break;
- }
-
- RefPtr<BufferResourceImpl> buffer(new BufferResourceImpl(initialUsage, desc, this));
- SLANG_RETURN_NULL_ON_FAIL(buffer->m_buffer.init(m_api, desc.sizeInBytes, usage, reqMemoryProperties));
-
- if ((desc.cpuAccessFlags & Resource::AccessFlag::Write) || initData)
- {
- SLANG_RETURN_NULL_ON_FAIL(buffer->m_uploadBuffer.init(m_api, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
- }
-
- if (initData)
- {
- // TODO: only create staging buffer if the memory type
- // used for the buffer doesn't let us fill things in
- // directly.
- // Copy into staging buffer
- void* mappedData = nullptr;
- SLANG_VK_CHECK(m_api.vkMapMemory(m_device, buffer->m_uploadBuffer.m_memory, 0, bufferSize, 0, &mappedData));
- ::memcpy(mappedData, initData, bufferSize);
- m_api.vkUnmapMemory(m_device, buffer->m_uploadBuffer.m_memory);
-
- // Copy from staging buffer to real buffer
- VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer();
-
- VkBufferCopy copyInfo = {};
- copyInfo.size = bufferSize;
- m_api.vkCmdCopyBuffer(commandBuffer, buffer->m_uploadBuffer.m_buffer, buffer->m_buffer.m_buffer, 1, &copyInfo);
-
- //flushCommandBuffer(commandBuffer);
- }
-
- return buffer.detach();
-}
-
-InputLayout* VKRenderer::createInputLayout(const InputElementDesc* elements, UInt numElements)
-{
- RefPtr<InputLayoutImpl> layout(new InputLayoutImpl);
-
- List<VkVertexInputAttributeDescription>& dstVertexDescs = layout->m_vertexDescs;
-
- size_t vertexSize = 0;
- dstVertexDescs.SetSize(numElements);
-
- for (UInt i = 0; i < numElements; ++i)
- {
- const InputElementDesc& srcDesc = elements[i];
- VkVertexInputAttributeDescription& dstDesc = dstVertexDescs[i];
-
- dstDesc.location = uint32_t(i);
- dstDesc.binding = 0;
- dstDesc.format = VulkanUtil::getVkFormat(srcDesc.format);
- if (dstDesc.format == VK_FORMAT_UNDEFINED)
- {
- return nullptr;
- }
-
- dstDesc.offset = uint32_t(srcDesc.offset);
-
- const size_t elementSize = RendererUtil::getFormatSize(srcDesc.format);
- assert(elementSize > 0);
- const size_t endElement = srcDesc.offset + elementSize;
-
- vertexSize = (vertexSize < endElement) ? endElement : vertexSize;
- }
-
- // Work out the overall size
- layout->m_vertexSize = int(vertexSize);
- return layout.detach();
-}
-
-void* VKRenderer::map(BufferResource* bufferIn, MapFlavor flavor)
-{
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(bufferIn);
- assert(buffer->m_mapFlavor == MapFlavor::Unknown);
-
- // Make sure everything has completed before reading...
- m_deviceQueue.flushAndWait();
-
- const size_t bufferSize = buffer->getDesc().sizeInBytes;
-
- switch (flavor)
- {
- case MapFlavor::WriteDiscard:
- case MapFlavor::HostWrite:
- {
- if (!buffer->m_uploadBuffer.isInitialized())
- {
- return nullptr;
- }
-
- void* mappedData = nullptr;
- SLANG_VK_CHECK(m_api.vkMapMemory(m_device, buffer->m_uploadBuffer.m_memory, 0, bufferSize, 0, &mappedData));
- buffer->m_mapFlavor = flavor;
- return mappedData;
- }
- case MapFlavor::HostRead:
- {
- // Make sure there is space in the read buffer
- buffer->m_readBuffer.SetSize(bufferSize);
-
- // create staging buffer
- Buffer staging;
-
- SLANG_RETURN_NULL_ON_FAIL(staging.init(m_api, 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 = m_deviceQueue.getCommandBuffer();
-
- VkBufferCopy copyInfo = {};
- copyInfo.size = bufferSize;
- m_api.vkCmdCopyBuffer(commandBuffer, buffer->m_buffer.m_buffer, staging.m_buffer, 1, &copyInfo);
-
- m_deviceQueue.flushAndWait();
-
- // Write out the data from the buffer
- void* mappedData = nullptr;
- SLANG_VK_CHECK(m_api.vkMapMemory(m_device, staging.m_memory, 0, bufferSize, 0, &mappedData));
-
- ::memcpy(buffer->m_readBuffer.Buffer(), mappedData, bufferSize);
- m_api.vkUnmapMemory(m_device, staging.m_memory);
-
- buffer->m_mapFlavor = flavor;
-
- return buffer->m_readBuffer.Buffer();
- }
- default:
- return nullptr;
- }
-}
-
-void VKRenderer::unmap(BufferResource* bufferIn)
-{
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(bufferIn);
- assert(buffer->m_mapFlavor != MapFlavor::Unknown);
-
- const size_t bufferSize = buffer->getDesc().sizeInBytes;
-
- switch (buffer->m_mapFlavor)
- {
- case MapFlavor::WriteDiscard:
- case MapFlavor::HostWrite:
- {
- m_api.vkUnmapMemory(m_device, buffer->m_uploadBuffer.m_memory);
-
- // Copy from staging buffer to real buffer
- VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer();
-
- VkBufferCopy copyInfo = {};
- copyInfo.size = bufferSize;
- m_api.vkCmdCopyBuffer(commandBuffer, buffer->m_uploadBuffer.m_buffer, buffer->m_buffer.m_buffer, 1, &copyInfo);
-
- // TODO: is this necessary?
- //m_deviceQueue.flushAndWait();
- break;
- }
- default: break;
- }
-
- // Mark as no longer mapped
- buffer->m_mapFlavor = MapFlavor::Unknown;
-}
-
-void VKRenderer::setInputLayout(InputLayout* inputLayout)
-{
- m_currentInputLayout = static_cast<InputLayoutImpl*>(inputLayout);
-}
-
-void VKRenderer::setPrimitiveTopology(PrimitiveTopology topology)
-{
- m_primitiveTopology = VulkanUtil::getVkPrimitiveTopology(topology);
-}
-
-void VKRenderer::setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets)
-{
- {
- const UInt num = startSlot + slotCount;
- if (num > m_boundVertexBuffers.Count())
- {
- m_boundVertexBuffers.SetSize(num);
- }
- }
-
- for (UInt i = 0; i < slotCount; i++)
- {
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[i]);
- if (buffer)
- {
- assert(buffer->m_initialUsage == Resource::Usage::VertexBuffer);
- }
-
- BoundVertexBuffer& boundBuffer = m_boundVertexBuffers[startSlot + i];
- boundBuffer.m_buffer = buffer;
- boundBuffer.m_stride = int(strides[i]);
- boundBuffer.m_offset = int(offsets[i]);
- }
-}
-
-void VKRenderer::setShaderProgram(ShaderProgram* program)
-{
- m_currentProgram = (ShaderProgramImpl*)program;
-}
-
-void VKRenderer::draw(UInt vertexCount, UInt startVertex = 0)
-{
- Pipeline* pipeline = _getPipeline();
- if (!pipeline || pipeline->m_shaderProgram->m_pipelineType != PipelineType::Graphics)
- {
- assert(!"Invalid render pipeline");
- return;
- }
-
- SLANG_RETURN_VOID_ON_FAIL(_beginPass());
-
- // Also create descriptor sets based on the given pipeline layout
- VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer();
-
- m_api.vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->m_pipeline);
- m_api.vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->m_pipelineLayout,
- 0, 1, &pipeline->m_descriptorSet, 0, nullptr);
-
- // Bind the vertex buffer
- if (m_boundVertexBuffers.Count() > 0 && m_boundVertexBuffers[0].m_buffer)
- {
- const BoundVertexBuffer& boundVertexBuffer = m_boundVertexBuffers[0];
-
- VkBuffer vertexBuffers[] = { boundVertexBuffer.m_buffer->m_buffer.m_buffer };
- VkDeviceSize offsets[] = { VkDeviceSize(boundVertexBuffer.m_offset) };
-
- m_api.vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
- }
-
- m_api.vkCmdDraw(commandBuffer, static_cast<uint32_t>(vertexCount), 1, 0, 0);
-
- _endPass();
-}
-
-void VKRenderer::dispatchCompute(int x, int y, int z)
-{
- Pipeline* pipeline = _getPipeline();
- if (!pipeline || pipeline->m_shaderProgram->m_pipelineType != PipelineType::Compute)
- {
- assert(!"Invalid render pipeline");
- return;
- }
-
- // Also create descriptor sets based on the given pipeline layout
- VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer();
-
- m_api.vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->m_pipeline);
-
- m_api.vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->m_pipelineLayout,
- 0, 1, &pipeline->m_descriptorSet, 0, nullptr);
-
- m_api.vkCmdDispatch(commandBuffer, x, y, z);
-}
-
-static VkImageViewType _calcImageViewType(TextureResource::Type type, const TextureResource::Desc& desc)
-{
- switch (type)
- {
- case Resource::Type::Texture1D: return desc.arraySize > 1 ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_1D;
- case Resource::Type::Texture2D: return desc.arraySize > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
- case Resource::Type::TextureCube: return desc.arraySize > 1 ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE;
- case Resource::Type::Texture3D:
- {
- // Can't have an array and 3d texture
- assert(desc.arraySize <= 1);
- if (desc.arraySize <= 1)
- {
- return VK_IMAGE_VIEW_TYPE_3D;
- }
- break;
- }
- default: break;
- }
-
- return VK_IMAGE_VIEW_TYPE_MAX_ENUM;
-}
-
-
-BindingState* VKRenderer::createBindingState(const BindingState::Desc& bindingStateDesc)
-{
- RefPtr<BindingStateImpl> bindingState(new BindingStateImpl(bindingStateDesc, &m_api));
-
- const auto& srcBindings = bindingStateDesc.m_bindings;
- const int numBindings = int(srcBindings.Count());
-
- auto& dstDetails = bindingState->m_bindingDetails;
- dstDetails.SetSize(numBindings);
-
- for (int i = 0; i < numBindings; ++i)
- {
- auto& dstDetail = dstDetails[i];
- const auto& srcBinding = srcBindings[i];
-
- switch (srcBinding.bindingType)
- {
- case BindingType::Buffer:
- {
- if (!srcBinding.resource || !srcBinding.resource->isBuffer())
- {
- assert(!"Needs to have a buffer resource set");
- return nullptr;
- }
-
- BufferResourceImpl* bufferResource = static_cast<BufferResourceImpl*>(srcBinding.resource.Ptr());
- const BufferResource::Desc& bufferResourceDesc = bufferResource->getDesc();
-
- if (bufferResourceDesc.bindFlags & Resource::BindFlag::UnorderedAccess)
- {
- // VkBufferView uav
-
- VkBufferViewCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO };
-
- info.format = VK_FORMAT_R32_SFLOAT;
- // TODO:
- // Not sure how to handle typeless?
- if (bufferResourceDesc.elementSize == 0)
- {
- info.format = VK_FORMAT_R32_SFLOAT; // DXGI_FORMAT_R32_TYPELESS ?
- }
-
- info.buffer = bufferResource->m_buffer.m_buffer;
- info.offset = 0;
- info.range = bufferResourceDesc.sizeInBytes;
-
- SLANG_VK_RETURN_NULL_ON_FAIL(m_api.vkCreateBufferView(m_device, &info, nullptr, &dstDetail.m_uav));
- }
-
- // TODO: Setup views.
- // VkImageView srv
-
-
- break;
- }
- case BindingType::Sampler:
- {
- VkSamplerCreateInfo samplerInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
-
- samplerInfo.magFilter = VK_FILTER_LINEAR;
- samplerInfo.minFilter = VK_FILTER_LINEAR;
-
- samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
- samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
- samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
-
- samplerInfo.anisotropyEnable = VK_FALSE;
- samplerInfo.maxAnisotropy = 1;
-
- samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
- samplerInfo.unnormalizedCoordinates = VK_FALSE;
- samplerInfo.compareEnable = VK_FALSE;
- samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
- samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
-
- SLANG_VK_RETURN_NULL_ON_FAIL(m_api.vkCreateSampler(m_device, &samplerInfo, nullptr, &dstDetail.m_sampler));
-
- break;
- }
- case BindingType::Texture:
- {
- if (!srcBinding.resource || !srcBinding.resource->isTexture())
- {
- assert(!"Needs to have a texture resource set");
- return nullptr;
- }
-
- TextureResourceImpl* textureResource = static_cast<TextureResourceImpl*>(srcBinding.resource.Ptr());
- const TextureResource::Desc& texDesc = textureResource->getDesc();
-
- VkImageViewType imageViewType = _calcImageViewType(textureResource->getType(), texDesc);
- if (imageViewType == VK_IMAGE_VIEW_TYPE_MAX_ENUM)
- {
- assert(!"Invalid view type");
- return nullptr;
- }
- const VkFormat format = VulkanUtil::getVkFormat(texDesc.format);
- if (format == VK_FORMAT_UNDEFINED)
- {
- assert(!"Unhandled image format");
- return nullptr;
- }
-
- // Create the image view
-
- VkImageViewCreateInfo viewInfo = {};
- viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- viewInfo.image = textureResource->m_image;
- viewInfo.viewType = imageViewType;
- viewInfo.format = format;
- viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- viewInfo.subresourceRange.baseMipLevel = 0;
- viewInfo.subresourceRange.levelCount = 1;
- viewInfo.subresourceRange.baseArrayLayer = 0;
- viewInfo.subresourceRange.layerCount = 1;
-
- viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
- viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
- viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
- viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
-
- SLANG_VK_RETURN_NULL_ON_FAIL(m_api.vkCreateImageView(m_device, &viewInfo, nullptr, &dstDetail.m_srv));
-
- break;
- }
- case BindingType::CombinedTextureSampler:
- {
- assert(!"not implemented");
- return nullptr;
- }
- }
- }
-
- return bindingState.detach();;
-}
-
-void VKRenderer::setBindingState(BindingState* state)
-{
- m_currentBindingState = static_cast<BindingStateImpl*>(state);
-}
-
-ShaderProgram* VKRenderer::createProgram(const ShaderProgram::Desc& desc)
-{
- ShaderProgramImpl* impl = new ShaderProgramImpl(desc.pipelineType);
- if( desc.pipelineType == PipelineType::Compute)
- {
- auto computeKernel = desc.findKernel(StageType::Compute);
- impl->m_compute = compileEntryPoint(*computeKernel, VK_SHADER_STAGE_COMPUTE_BIT, impl->m_buffers[0]);
- }
- else
- {
- auto vertexKernel = desc.findKernel(StageType::Vertex);
- auto fragmentKernel = desc.findKernel(StageType::Fragment);
-
- impl->m_vertex = compileEntryPoint(*vertexKernel, VK_SHADER_STAGE_VERTEX_BIT, impl->m_buffers[0]);
- impl->m_fragment = compileEntryPoint(*fragmentKernel, VK_SHADER_STAGE_FRAGMENT_BIT, impl->m_buffers[1]);
- }
- return impl;
-}
-
-} // renderer_test