summaryrefslogtreecommitdiffstats
path: root/tools/gfx/render-vk.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-09-13 15:59:15 -0400
committerGitHub <noreply@github.com>2019-09-13 15:59:15 -0400
commitc2e5d2468ad6a38cdb8a067da0678302f6cc6066 (patch)
tree97c448d28e54068d84c422e9f172996b7a95f1ed /tools/gfx/render-vk.cpp
parent0b6321b3f08c48e37e6b8256d420f05d9727fb5a (diff)
Refactor render-test to make cross platform (#1053)
* First pass of render-test refactor. * Make window construction a function that can choose an implementation. * Remove OpenGL as currently has windows dependency. * Disable Vulkan as Renderer impl has dependency on windows. * Pass Window in as parameter of 'update'. * Add win-window.cpp as was missing. * Fix warning on windows about signs during comparison.
Diffstat (limited to 'tools/gfx/render-vk.cpp')
-rw-r--r--tools/gfx/render-vk.cpp2793
1 files changed, 0 insertions, 2793 deletions
diff --git a/tools/gfx/render-vk.cpp b/tools/gfx/render-vk.cpp
deleted file mode 100644
index 77b593565..000000000
--- a/tools/gfx/render-vk.cpp
+++ /dev/null
@@ -1,2793 +0,0 @@
-// render-vk.cpp
-#include "render-vk.h"
-
-//WORKING:#include "options.h"
-#include "render.h"
-
-#include "../../source/core/slang-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 gfx {
-using namespace Slang;
-
-class VKRenderer : public Renderer
-{
-public:
- enum
- {
- kMaxRenderTargets = 8,
- kMaxAttachments = kMaxRenderTargets + 1,
-
- kMaxDescriptorSets = 4,
- };
-
- // Renderer implementation
- virtual SlangResult initialize(const Desc& desc, void* inWindowHandle) override;
- virtual const List<String>& getFeatures() override { return m_features; }
- virtual void setClearColor(const float color[4]) override;
- virtual void clearFrame() override;
- virtual void presentFrame() override;
- TextureResource::Desc getSwapChainTextureDesc() override;
-
- Result createTextureResource(Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData, TextureResource** outResource) override;
- Result createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& desc, const void* initData, BufferResource** outResource) override;
- Result createSamplerState(SamplerState::Desc const& desc, SamplerState** outSampler) override;
-
- Result createTextureView(TextureResource* texture, ResourceView::Desc const& desc, ResourceView** outView) override;
- Result createBufferView(BufferResource* buffer, ResourceView::Desc const& desc, ResourceView** outView) override;
-
- Result createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount, InputLayout** outLayout) override;
-
- Result createDescriptorSetLayout(const DescriptorSetLayout::Desc& desc, DescriptorSetLayout** outLayout) override;
- Result createPipelineLayout(const PipelineLayout::Desc& desc, PipelineLayout** outLayout) override;
- Result createDescriptorSet(DescriptorSetLayout* layout, DescriptorSet** outDescriptorSet) override;
-
- Result createProgram(const ShaderProgram::Desc& desc, ShaderProgram** outProgram) override;
- Result createGraphicsPipelineState(const GraphicsPipelineStateDesc& desc, PipelineState** outState) override;
- Result createComputePipelineState(const ComputePipelineStateDesc& desc, PipelineState** outState) override;
-
- virtual SlangResult captureScreenSurface(Surface& surface) override;
-
- virtual void* map(BufferResource* buffer, MapFlavor flavor) override;
- virtual void unmap(BufferResource* buffer) override;
- virtual void setPrimitiveTopology(PrimitiveTopology topology) override;
-
- virtual void setDescriptorSet(PipelineType pipelineType, PipelineLayout* layout, UInt index, DescriptorSet* descriptorSet) override;
-
- virtual void setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets) override;
- virtual void setIndexBuffer(BufferResource* buffer, Format indexFormat, UInt offset) override;
- virtual void setDepthStencilTarget(ResourceView* depthStencilView) override;
- void setViewports(UInt count, Viewport const* viewports) override;
- void setScissorRects(UInt count, ScissorRect const* rects) override;
- virtual void setPipelineState(PipelineType pipelineType, PipelineState* state) override;
- virtual void draw(UInt vertexCount, UInt startVertex) override;
- virtual void drawIndexed(UInt indexCount, UInt startIndex, UInt baseVertex) 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 SamplerStateImpl : public SamplerState
- {
- public:
- VkSampler m_sampler;
- };
-
- class ResourceViewImpl : public ResourceView
- {
- public:
- enum class ViewType
- {
- Texture,
- TexelBuffer,
- PlainBuffer,
- };
- ViewType m_type;
- };
-
- class TextureResourceViewImpl : public ResourceViewImpl
- {
- public:
- TextureResourceViewImpl()
- {
- m_type = ViewType::Texture;
- }
-
- RefPtr<TextureResourceImpl> m_texture;
- VkImageView m_view;
- VkImageLayout m_layout;
- };
-
- class TexelBufferResourceViewImpl : public ResourceViewImpl
- {
- public:
- TexelBufferResourceViewImpl()
- {
- m_type = ViewType::TexelBuffer;
- }
-
- RefPtr<BufferResourceImpl> m_buffer;
- VkBufferView m_view;
- };
-
- class PlainBufferResourceViewImpl : public ResourceViewImpl
- {
- public:
- PlainBufferResourceViewImpl()
- {
- m_type = ViewType::PlainBuffer;
- }
-
- RefPtr<BufferResourceImpl> m_buffer;
- VkDeviceSize offset;
- VkDeviceSize size;
- };
-
- 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
- };
-
- class DescriptorSetLayoutImpl : public DescriptorSetLayout
- {
- public:
- DescriptorSetLayoutImpl(const VulkanApi& api)
- : m_api(&api)
- {
- }
-
- ~DescriptorSetLayoutImpl()
- {
- if(m_descriptorSetLayout != VK_NULL_HANDLE)
- {
- m_api->vkDestroyDescriptorSetLayout(m_api->m_device, m_descriptorSetLayout, nullptr);
- }
- if (m_descriptorPool != VK_NULL_HANDLE)
- {
- m_api->vkDestroyDescriptorPool(m_api->m_device, m_descriptorPool, nullptr);
- }
- }
-
- VulkanApi const* m_api;
- VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE;
- VkDescriptorPool m_descriptorPool = VK_NULL_HANDLE;
-
- struct RangeInfo
- {
- VkDescriptorType descriptorType;
- };
- List<RangeInfo> m_ranges;
- };
-
- class PipelineLayoutImpl : public PipelineLayout
- {
- public:
- PipelineLayoutImpl(const VulkanApi& api)
- : m_api(&api)
- {
- }
-
- ~PipelineLayoutImpl()
- {
- if (m_pipelineLayout != VK_NULL_HANDLE)
- {
- m_api->vkDestroyPipelineLayout(m_api->m_device, m_pipelineLayout, nullptr);
- }
- }
-
- VulkanApi const* m_api;
- VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
- UInt m_descriptorSetCount = 0;
- };
-
- class DescriptorSetImpl : public DescriptorSet
- {
- public:
- // Record the view binding
- struct Binding
- {
- enum class Type : uint8_t
- {
- Unknown,
- ResourceView,
- SamplerState,
- BufferResource,
- CountOf,
- };
- Type type;
- uint32_t range;
- uint32_t index;
- RefPtr<RefObject> obj;
- };
-
- DescriptorSetImpl(VKRenderer* renderer)
- : m_renderer(renderer)
- {
- }
-
- ~DescriptorSetImpl()
- {
- }
-
- virtual void setConstantBuffer(UInt range, UInt index, BufferResource* buffer) override;
- virtual void setResource(UInt range, UInt index, ResourceView* view) override;
- virtual void setSampler(UInt range, UInt index, SamplerState* sampler) override;
- virtual void setCombinedTextureSampler(
- UInt range,
- UInt index,
- ResourceView* textureView,
- SamplerState* sampler) override;
-
- static Binding::Type _getBindingType(RefObject* ptr);
- void _setBinding(Binding::Type type, UInt range, UInt index, RefObject* ptr);
-
- VKRenderer* m_renderer = nullptr; ///< Weak pointer, can't be strong, because if set will become circular reference
- RefPtr<DescriptorSetLayoutImpl> m_layout;
- VkDescriptorSet m_descriptorSet = VK_NULL_HANDLE;
-
- List<Binding> m_bindings; ///< Records entities are bound to this descriptor set, and keeps the associated resources/views/state in scope
- };
-
-#if 0
- 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;
- };
-#endif
-
- struct BoundVertexBuffer
- {
- RefPtr<BufferResourceImpl> m_buffer;
- int m_stride;
- int m_offset;
- };
-
- class PipelineStateImpl : public PipelineState
- {
- public:
- PipelineStateImpl(const VulkanApi& api):
- m_api(&api)
- {
- }
- ~PipelineStateImpl()
- {
- if (m_pipeline != VK_NULL_HANDLE)
- {
- m_api->vkDestroyPipeline(m_api->m_device, m_pipeline, nullptr);
- }
- }
-
- const VulkanApi* m_api;
-
-// VkPrimitiveTopology m_primitiveTopology;
-
- RefPtr<PipelineLayoutImpl> m_pipelineLayout;
-
-// RefPtr<InputLayoutImpl> m_inputLayout;
- RefPtr<ShaderProgramImpl> m_shaderProgram;
-
- 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<PipelineLayoutImpl> m_currentPipelineLayout;
-
- RefPtr<DescriptorSetImpl> m_currentDescriptorSetImpls [kMaxDescriptorSets];
- VkDescriptorSet m_currentDescriptorSets [kMaxDescriptorSets];
-
-// RefPtr<ShaderProgramImpl> m_currentProgram;
-
-// List<RefPtr<Pipeline> > m_pipelineCache;
- RefPtr<PipelineStateImpl> m_currentPipeline;
-
- 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;
- List<String> m_features;
-};
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 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 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-#if 0
-bool VKRenderer::_isEqual(const Pipeline& pipeline) const
-{
- return
- pipeline.m_pipelineLayout == m_currentPipelineLayout &&
- 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_pipelineLayout = m_currentPipelineLayout;
- 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));
-
- 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->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.getBuffer();
- }
-
- //
-
- 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->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;
-}
-#endif
-
-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.setCount(bufferSize);
- char* buffer = bufferArray.getBuffer();
-
- 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.getBuffer();
-
- 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,
-
- VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_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.setCount(numPhysicalDevices);
- SLANG_VK_RETURN_ON_FAIL(m_api.vkEnumeratePhysicalDevices(instance, &numPhysicalDevices, physicalDevices.getBuffer()));
-
- Index selectedDeviceIndex = 0;
-
- if (desc.adapter.getLength())
- {
- selectedDeviceIndex = -1;
-
- String lowerAdapter = desc.adapter.toLower();
-
- for (Index i = 0; i < physicalDevices.getCount(); ++i)
- {
- auto physicalDevice = physicalDevices[i];
-
- VkPhysicalDeviceProperties basicProps = {};
- m_api.vkGetPhysicalDeviceProperties(physicalDevice, &basicProps);
-
- String lowerName = String(basicProps.deviceName).toLower();
-
- if (lowerName.indexOf(lowerAdapter) != Index(-1))
- {
- selectedDeviceIndex = i;
- break;
- }
- }
- if (selectedDeviceIndex < 0)
- {
- // Device not found
- return SLANG_FAIL;
- }
- }
-
- SLANG_RETURN_ON_FAIL(m_api.initPhysicalDevice(physicalDevices[selectedDeviceIndex]));
-
- List<const char*> deviceExtensions;
- deviceExtensions.add(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
-
- VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
- deviceCreateInfo.queueCreateInfoCount = 1;
-
- deviceCreateInfo.pEnabledFeatures = &m_api.m_deviceFeatures;
-
- // Get the device features (doesn't use, but useful when debugging)
- if (m_api.vkGetPhysicalDeviceFeatures2)
- {
- VkPhysicalDeviceFeatures2 deviceFeatures2 = {};
- deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
- m_api.vkGetPhysicalDeviceFeatures2(m_api.m_physicalDevice, &deviceFeatures2);
- }
-
- VkPhysicalDeviceProperties basicProps = {};
- m_api.vkGetPhysicalDeviceProperties(m_api.m_physicalDevice, &basicProps);
-
- // Get the API version
- const uint32_t majorVersion = VK_VERSION_MAJOR(basicProps.apiVersion);
- const uint32_t minorVersion = VK_VERSION_MINOR(basicProps.apiVersion);
-
- // Float16 features
- // Need in this scope because it will be linked into the device creation (if it is available)
- VkPhysicalDeviceFloat16Int8FeaturesKHR float16Features = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR };
-
- // API version check, can't use vkGetPhysicalDeviceProperties2 yet since this device might not support it
- if (VK_MAKE_VERSION(majorVersion, minorVersion, 0) >= VK_API_VERSION_1_1 &&
- m_api.vkGetPhysicalDeviceProperties2 &&
- m_api.vkGetPhysicalDeviceFeatures2)
- {
- VkPhysicalDeviceProperties2 physicalDeviceProps2;
-
- physicalDeviceProps2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
- physicalDeviceProps2.pNext = nullptr;
- physicalDeviceProps2.properties = {};
-
- m_api.vkGetPhysicalDeviceProperties2(m_api.m_physicalDevice, &physicalDeviceProps2);
-
- // Get device features
- VkPhysicalDeviceFeatures2 deviceFeatures2 = {};
- deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
-
- // Link together for lookup
- float16Features.pNext = deviceFeatures2.pNext;
- deviceFeatures2.pNext = &float16Features;
-
- m_api.vkGetPhysicalDeviceFeatures2(m_api.m_physicalDevice, &deviceFeatures2);
-
- // If we have float16 features then enable
- if (float16Features.shaderFloat16)
- {
- // Link into the creation features
- float16Features.pNext = (void*)deviceCreateInfo.pNext;
- deviceCreateInfo.pNext = &float16Features;
-
- // Add the Float16 extension
- deviceExtensions.add(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME);
-
- // We have half support
- m_features.add("half");
- }
- }
-
- 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;
-
- deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
-
- deviceCreateInfo.enabledExtensionCount = uint32_t(deviceExtensions.getCount());
- deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.getBuffer();
-
- 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();
-}
-
-TextureResource::Desc VKRenderer::getSwapChainTextureDesc()
-{
- TextureResource::Desc desc;
- desc.init2D(Resource::Type::Texture2D, Format::Unknown, m_desc.width, m_desc.height, 1);
- return desc;
-}
-
-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);
-}
-
-Result VKRenderer::createTextureResource(Resource::Usage initialUsage, const TextureResource::Desc& descIn, const TextureResource::Data* initData, TextureResource** outResource)
-{
- TextureResource::Desc desc(descIn);
- desc.setDefaults(initialUsage);
-
- const VkFormat format = VulkanUtil::getVkFormat(desc.format);
- if (format == VK_FORMAT_UNDEFINED)
- {
- assert(!"Unhandled image format");
- return SLANG_FAIL;
- }
-
- 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 SLANG_FAIL;
- }
- }
-
- 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_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_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_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.getCount() == 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 (Index j = 0; j < mipSizes.getCount(); ++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 (Index j = 0; j < mipSizes.getCount(); ++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 = uint32_t(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();
- }
-
- *outResource = texture.detach();
- return SLANG_OK;
-}
-
-Result VKRenderer::createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData, BufferResource** outResource)
-{
- 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_ON_FAIL(buffer->m_buffer.init(m_api, desc.sizeInBytes, usage, reqMemoryProperties));
-
- if ((desc.cpuAccessFlags & Resource::AccessFlag::Write) || initData)
- {
- SLANG_RETURN_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);
- }
-
- *outResource = buffer.detach();
- return SLANG_OK;
-}
-
-
-VkFilter translateFilterMode(TextureFilteringMode mode)
-{
- switch (mode)
- {
- default:
- return VkFilter(0);
-
-#define CASE(SRC, DST) \
- case TextureFilteringMode::SRC: return VK_FILTER_##DST
-
- CASE(Point, NEAREST);
- CASE(Linear, LINEAR);
-
-#undef CASE
- }
-}
-
-VkSamplerMipmapMode translateMipFilterMode(TextureFilteringMode mode)
-{
- switch (mode)
- {
- default:
- return VkSamplerMipmapMode(0);
-
-#define CASE(SRC, DST) \
- case TextureFilteringMode::SRC: return VK_SAMPLER_MIPMAP_MODE_##DST
-
- CASE(Point, NEAREST);
- CASE(Linear, LINEAR);
-
-#undef CASE
- }
-}
-
-VkSamplerAddressMode translateAddressingMode(TextureAddressingMode mode)
-{
- switch (mode)
- {
- default:
- return VkSamplerAddressMode(0);
-
-#define CASE(SRC, DST) \
- case TextureAddressingMode::SRC: return VK_SAMPLER_ADDRESS_MODE_##DST
-
- CASE(Wrap, REPEAT);
- CASE(ClampToEdge, CLAMP_TO_EDGE);
- CASE(ClampToBorder, CLAMP_TO_BORDER);
- CASE(MirrorRepeat, MIRRORED_REPEAT);
- CASE(MirrorOnce, MIRROR_CLAMP_TO_EDGE);
-
-#undef CASE
- }
-}
-
-static VkCompareOp translateComparisonFunc(ComparisonFunc func)
-{
- switch (func)
- {
- default:
- // TODO: need to report failures
- return VK_COMPARE_OP_ALWAYS;
-
-#define CASE(FROM, TO) \
- case ComparisonFunc::FROM: return VK_COMPARE_OP_##TO
-
- CASE(Never, NEVER);
- CASE(Less, LESS);
- CASE(Equal, EQUAL);
- CASE(LessEqual, LESS_OR_EQUAL);
- CASE(Greater, GREATER);
- CASE(NotEqual, NOT_EQUAL);
- CASE(GreaterEqual, GREATER_OR_EQUAL);
- CASE(Always, ALWAYS);
-#undef CASE
- }
-}
-
-Result VKRenderer::createSamplerState(SamplerState::Desc const& desc, SamplerState** outSampler)
-{
- VkSamplerCreateInfo samplerInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
-
- samplerInfo.magFilter = translateFilterMode(desc.minFilter);
- samplerInfo.minFilter = translateFilterMode(desc.magFilter);
-
- samplerInfo.addressModeU = translateAddressingMode(desc.addressU);
- samplerInfo.addressModeV = translateAddressingMode(desc.addressV);
- samplerInfo.addressModeW = translateAddressingMode(desc.addressW);
-
- samplerInfo.anisotropyEnable = desc.maxAnisotropy > 1;
- samplerInfo.maxAnisotropy = (float) desc.maxAnisotropy;
-
- // TODO: support translation of border color...
- samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
-
- samplerInfo.unnormalizedCoordinates = VK_FALSE;
- samplerInfo.compareEnable = desc.reductionOp == TextureReductionOp::Comparison;
- samplerInfo.compareOp = translateComparisonFunc(desc.comparisonFunc);
- samplerInfo.mipmapMode = translateMipFilterMode(desc.mipFilter);
-
- VkSampler sampler;
- SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateSampler(m_device, &samplerInfo, nullptr, &sampler));
-
- RefPtr<SamplerStateImpl> samplerImpl = new SamplerStateImpl();
- samplerImpl->m_sampler = sampler;
- *outSampler = samplerImpl.detach();
- return SLANG_OK;
-}
-
-Result VKRenderer::createTextureView(TextureResource* texture, ResourceView::Desc const& desc, ResourceView** outView)
-{
- assert(!"unimplemented");
- return SLANG_FAIL;
-}
-
-Result VKRenderer::createBufferView(BufferResource* buffer, ResourceView::Desc const& desc, ResourceView** outView)
-{
- auto resourceImpl = (BufferResourceImpl*) buffer;
-
- // TODO: These should come from the `ResourceView::Desc`
- VkDeviceSize offset = 0;
- VkDeviceSize size = resourceImpl->getDesc().sizeInBytes;
-
- // There are two different cases we need to think about for buffers.
- //
- // One is when we have a "uniform texel buffer" or "storage texel buffer,"
- // in which case we need to construct a `VkBufferView` to represent the
- // formatting that is applied to the buffer. This case would correspond
- // to a `textureBuffer` or `imageBuffer` in GLSL, and more or less to
- // `Buffer<..>` or `RWBuffer<...>` in HLSL.
- //
- // The other case is a `storage buffer` which is the catch-all for any
- // non-formatted R/W access to a buffer. In GLSL this is a `buffer { ... }`
- // declaration, while in HLSL it covers a bunch of different `RW*Buffer`
- // cases. In these cases we do *not* need a `VkBufferView`, but in
- // order to be compatible with other APIs that require views for any
- // potentially writable access, we will have to create one anyway.
- //
- // We will distinguish the two cases by looking at whether the view
- // is being requested with a format or not.
- //
-
- switch(desc.type)
- {
- default:
- assert(!"unhandled");
- return SLANG_FAIL;
-
- case ResourceView::Type::UnorderedAccess:
- // Is this a formatted view?
- //
- if(desc.format == Format::Unknown)
- {
- // Buffer usage that doesn't involve formatting doesn't
- // require a view in Vulkan.
- RefPtr<PlainBufferResourceViewImpl> viewImpl = new PlainBufferResourceViewImpl();
- viewImpl->m_buffer = resourceImpl;
- viewImpl->offset = 0;
- viewImpl->size = size;
- *outView = viewImpl.detach();
- return SLANG_OK;
- }
- //
- // If the view is formatted, then we need to handle
- // it just like we would for a "sampled" buffer:
- //
- // FALLTHROUGH
- case ResourceView::Type::ShaderResource:
- {
- VkBufferViewCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO };
-
- info.format = VulkanUtil::getVkFormat(desc.format);
- info.buffer = resourceImpl->m_buffer.m_buffer;
- info.offset = offset;
- info.range = size;
-
- VkBufferView view;
- SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateBufferView(m_device, &info, nullptr, &view));
-
- RefPtr<TexelBufferResourceViewImpl> viewImpl = new TexelBufferResourceViewImpl();
- viewImpl->m_buffer = resourceImpl;
- viewImpl->m_view = view;
- *outView = viewImpl.detach();
- return SLANG_OK;
- }
- break;
- }
-}
-
-Result VKRenderer::createInputLayout(const InputElementDesc* elements, UInt numElements, InputLayout** outLayout)
-{
- RefPtr<InputLayoutImpl> layout(new InputLayoutImpl);
-
- List<VkVertexInputAttributeDescription>& dstVertexDescs = layout->m_vertexDescs;
-
- size_t vertexSize = 0;
- dstVertexDescs.setCount(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 SLANG_FAIL;
- }
-
- 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);
- *outLayout = layout.detach();
- return SLANG_OK;
-}
-
-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.setCount(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.getBuffer(), mappedData, bufferSize);
- m_api.vkUnmapMemory(m_device, staging.m_memory);
-
- buffer->m_mapFlavor = flavor;
-
- return buffer->m_readBuffer.getBuffer();
- }
- 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::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 Index num = Index(startSlot + slotCount);
- if (num > m_boundVertexBuffers.getCount())
- {
- m_boundVertexBuffers.setCount(num);
- }
- }
-
- for (Index i = 0; i < Index(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::setIndexBuffer(BufferResource* buffer, Format indexFormat, UInt offset)
-{
-}
-
-void VKRenderer::setDepthStencilTarget(ResourceView* depthStencilView)
-{
-}
-
-void VKRenderer::setViewports(UInt count, Viewport const* viewports)
-{
- static const int kMaxViewports = 8; // TODO: base on device caps
- assert(count <= kMaxViewports);
-
- VkViewport vkViewports[kMaxViewports];
- for(UInt ii = 0; ii < count; ++ii)
- {
- auto& inViewport = viewports[ii];
- auto& vkViewport = vkViewports[ii];
-
- vkViewport.x = inViewport.originX;
- vkViewport.y = inViewport.originY;
- vkViewport.width = inViewport.extentX;
- vkViewport.height = inViewport.extentY;
- vkViewport.minDepth = inViewport.minZ;
- vkViewport.maxDepth = inViewport.maxZ;
- }
-
- VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer();
- m_api.vkCmdSetViewport(commandBuffer, 0, uint32_t(count), vkViewports);
-}
-
-void VKRenderer::setScissorRects(UInt count, ScissorRect const* rects)
-{
- static const int kMaxScissorRects = 8; // TODO: base on device caps
- assert(count <= kMaxScissorRects);
-
- VkRect2D vkRects[kMaxScissorRects];
- for(UInt ii = 0; ii < count; ++ii)
- {
- auto& inRect = rects[ii];
- auto& vkRect = vkRects[ii];
-
- vkRect.offset.x = int32_t(inRect.minX);
- vkRect.offset.y = int32_t(inRect.minY);
- vkRect.extent.width = uint32_t(inRect.maxX - inRect.minX);
- vkRect.extent.height = uint32_t(inRect.maxY - inRect.minY);
- }
-
- VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer();
- m_api.vkCmdSetScissor(commandBuffer, 0, uint32_t(count), vkRects);
-}
-
-void VKRenderer::setPipelineState(PipelineType pipelineType, PipelineState* state)
-{
- m_currentPipeline = (PipelineStateImpl*)state;
-}
-
-void VKRenderer::draw(UInt vertexCount, UInt startVertex = 0)
-{
- auto pipeline = m_currentPipeline;
- 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);
-
- auto pipelineLayoutImpl = pipeline->m_pipelineLayout.Ptr();
- m_api.vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayoutImpl->m_pipelineLayout,
- 0, uint32_t(pipelineLayoutImpl->m_descriptorSetCount),
- &m_currentDescriptorSets[0],
- 0, nullptr);
-
- // Bind the vertex buffer
- if (m_boundVertexBuffers.getCount() > 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::drawIndexed(UInt indexCount, UInt startIndex, UInt baseVertex)
-{
-}
-
-void VKRenderer::dispatchCompute(int x, int y, int z)
-{
- auto pipeline = m_currentPipeline;
- if (!pipeline || pipeline->m_shaderProgram->m_pipelineType != PipelineType::Compute)
- {
- assert(!"Invalid compute 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);
-
- auto pipelineLayoutImpl = pipeline->m_pipelineLayout.Ptr();
- m_api.vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayoutImpl->m_pipelineLayout,
- 0, uint32_t(pipelineLayoutImpl->m_descriptorSetCount),
- &m_currentDescriptorSets[0],
- 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;
-}
-
-#if 0
-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();;
-}
-#endif
-
-static VkDescriptorType translateDescriptorType(DescriptorSlotType type)
-{
- switch(type)
- {
- default:
- return VK_DESCRIPTOR_TYPE_MAX_ENUM;
-
-#define CASE(SRC, DST) \
- case DescriptorSlotType::SRC: return VK_DESCRIPTOR_TYPE_##DST
-
- CASE(Sampler, SAMPLER);
- CASE(CombinedImageSampler, COMBINED_IMAGE_SAMPLER);
- CASE(SampledImage, SAMPLED_IMAGE);
- CASE(StorageImage, STORAGE_IMAGE);
- CASE(UniformTexelBuffer, UNIFORM_TEXEL_BUFFER);
- CASE(StorageTexelBuffer, STORAGE_TEXEL_BUFFER);
- CASE(UniformBuffer, UNIFORM_BUFFER);
- CASE(StorageBuffer, STORAGE_BUFFER);
- CASE(DynamicUniformBuffer, UNIFORM_BUFFER_DYNAMIC);
- CASE(DynamicStorageBuffer, STORAGE_BUFFER_DYNAMIC);
- CASE(InputAttachment, INPUT_ATTACHMENT);
-
-#undef CASE
- }
-}
-
-Result VKRenderer::createDescriptorSetLayout(const DescriptorSetLayout::Desc& desc, DescriptorSetLayout** outLayout)
-{
- RefPtr<DescriptorSetLayoutImpl> descriptorSetLayoutImpl = new DescriptorSetLayoutImpl(m_api);
-
- Slang::List<VkDescriptorSetLayoutBinding> dstBindings;
-
- uint32_t descriptorCountForTypes[VK_DESCRIPTOR_TYPE_RANGE_SIZE] = { 0, };
-
- UInt rangeCount = desc.slotRangeCount;
- for(UInt rr = 0; rr < rangeCount; ++rr)
- {
- auto& srcRange = desc.slotRanges[rr];
-
- VkDescriptorType dstDescriptorType = translateDescriptorType(srcRange.type);
-
- VkDescriptorSetLayoutBinding dstBinding;
- dstBinding.binding = uint32_t(rr);
- dstBinding.descriptorType = dstDescriptorType;
- dstBinding.descriptorCount = uint32_t(srcRange.count);
- dstBinding.stageFlags = VK_SHADER_STAGE_ALL;
- dstBinding.pImmutableSamplers = nullptr;
-
- descriptorCountForTypes[dstDescriptorType] += uint32_t(srcRange.count);
-
- dstBindings.add(dstBinding);
-
- DescriptorSetLayoutImpl::RangeInfo rangeInfo;
- rangeInfo.descriptorType = dstDescriptorType;
- descriptorSetLayoutImpl->m_ranges.add(rangeInfo);
- }
-
- VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
- descriptorSetLayoutInfo.bindingCount = uint32_t(dstBindings.getCount());
- descriptorSetLayoutInfo.pBindings = dstBindings.getBuffer();
-
- VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE;
- SLANG_VK_CHECK(m_api.vkCreateDescriptorSetLayout(m_device, &descriptorSetLayoutInfo, nullptr, &descriptorSetLayout));
-
- // Create a pool while we are at it, to allocate descriptor sets of this type.
-
- VkDescriptorPoolSize poolSizes[VK_DESCRIPTOR_TYPE_RANGE_SIZE];
- uint32_t poolSizeCount = 0;
- for (int ii = 0; ii < SLANG_COUNT_OF(descriptorCountForTypes); ++ii)
- {
- auto descriptorCount = descriptorCountForTypes[ii];
- if (descriptorCount > 0)
- {
- poolSizes[poolSizeCount].type = VkDescriptorType(ii);
- poolSizes[poolSizeCount].descriptorCount = descriptorCount;
- poolSizeCount++;
- }
- }
-
- VkDescriptorPoolCreateInfo descriptorPoolInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
- descriptorPoolInfo.maxSets = 128; // TODO: actually pick a size.
- descriptorPoolInfo.poolSizeCount = poolSizeCount;
- descriptorPoolInfo.pPoolSizes = &poolSizes[0];
-
- VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
- SLANG_VK_CHECK(m_api.vkCreateDescriptorPool(m_device, &descriptorPoolInfo, nullptr, &descriptorPool));
-
- descriptorSetLayoutImpl->m_descriptorSetLayout = descriptorSetLayout;
- descriptorSetLayoutImpl->m_descriptorPool = descriptorPool;
-
- *outLayout = descriptorSetLayoutImpl.detach();
- return SLANG_OK;
-}
-
-Result VKRenderer::createPipelineLayout(const PipelineLayout::Desc& desc, PipelineLayout** outLayout)
-{
- UInt descriptorSetCount = desc.descriptorSetCount;
-
- VkDescriptorSetLayout descriptorSetLayouts[kMaxDescriptorSets];
- for(UInt ii = 0; ii < descriptorSetCount; ++ii)
- {
- descriptorSetLayouts[ii] = ((DescriptorSetLayoutImpl*) desc.descriptorSets[ii].layout)->m_descriptorSetLayout;
- }
-
- VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
- pipelineLayoutInfo.setLayoutCount = uint32_t(desc.descriptorSetCount);
- pipelineLayoutInfo.pSetLayouts = &descriptorSetLayouts[0];
-
- VkPipelineLayout pipelineLayout;
- SLANG_VK_CHECK(m_api.vkCreatePipelineLayout(m_device, &pipelineLayoutInfo, nullptr, &pipelineLayout));
-
- RefPtr<PipelineLayoutImpl> pipelineLayoutImpl = new PipelineLayoutImpl(m_api);
- pipelineLayoutImpl->m_pipelineLayout = pipelineLayout;
- pipelineLayoutImpl->m_descriptorSetCount = descriptorSetCount;
-
- *outLayout = pipelineLayoutImpl.detach();
- return SLANG_OK;
-}
-
-Result VKRenderer::createDescriptorSet(DescriptorSetLayout* layout, DescriptorSet** outDescriptorSet)
-{
- auto layoutImpl = (DescriptorSetLayoutImpl*)layout;
-
- VkDescriptorSetAllocateInfo descriptorSetAllocInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
- descriptorSetAllocInfo.descriptorPool = layoutImpl->m_descriptorPool;
- descriptorSetAllocInfo.descriptorSetCount = 1;
- descriptorSetAllocInfo.pSetLayouts = &layoutImpl->m_descriptorSetLayout;
-
- VkDescriptorSet descriptorSet;
- SLANG_VK_CHECK(m_api.vkAllocateDescriptorSets(m_device, &descriptorSetAllocInfo, &descriptorSet));
-
- RefPtr<DescriptorSetImpl> descriptorSetImpl = new DescriptorSetImpl(this);
- descriptorSetImpl->m_layout = layoutImpl;
- descriptorSetImpl->m_descriptorSet = descriptorSet;
- *outDescriptorSet = descriptorSetImpl.detach();
- return SLANG_OK;
-}
-
-/* static */VKRenderer::DescriptorSetImpl::Binding::Type VKRenderer::DescriptorSetImpl::_getBindingType(RefObject* ptr)
-{
- typedef Binding::Type Type;
-
- if (ptr)
- {
- if (dynamic_cast<ResourceView*>(ptr))
- {
- return Type::ResourceView;
- }
- else if (dynamic_cast<BufferResource*>(ptr))
- {
- return Type::BufferResource;
- }
- else if (dynamic_cast<SamplerState*>(ptr))
- {
- return Type::SamplerState;
- }
- }
- return Type::Unknown;
-}
-
-void VKRenderer::DescriptorSetImpl::_setBinding(Binding::Type type, UInt range, UInt index, RefObject* ptr)
-{
- SLANG_ASSERT(ptr == nullptr || _getBindingType(ptr) == type);
-
- const Index numBindings = m_bindings.getCount();
- for (Index i = 0; i < numBindings; ++i)
- {
- Binding& binding = m_bindings[i];
-
- if (binding.type == type && binding.range == uint32_t(range) && binding.index == uint32_t(index))
- {
- if (ptr)
- {
- binding.obj = ptr;
- }
- else
- {
- m_bindings.removeAt(i);
- }
-
- return;
- }
- }
-
- // If an entry is not found, and we have a pointer, create an entry
- if (ptr)
- {
- Binding binding;
- binding.type = type;
- binding.range = uint32_t(range);
- binding.index = uint32_t(index);
- binding.obj = ptr;
-
- m_bindings.add(binding);
- }
-}
-
-void VKRenderer::DescriptorSetImpl::setConstantBuffer(UInt range, UInt index, BufferResource* buffer)
-{
- auto bufferImpl = (BufferResourceImpl*)buffer;
-
- VkDescriptorBufferInfo bufferInfo = {};
- bufferInfo.buffer = bufferImpl->m_buffer.m_buffer;
- bufferInfo.offset = 0;
- bufferInfo.range = bufferImpl->getDesc().sizeInBytes;
-
- VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
- writeInfo.dstBinding = uint32_t(range);
- writeInfo.dstArrayElement = uint32_t(index);
- writeInfo.descriptorCount = 1;
- writeInfo.descriptorType = m_layout->m_ranges[range].descriptorType;
- writeInfo.pBufferInfo = &bufferInfo;
-
- m_renderer->m_api.vkUpdateDescriptorSets(m_renderer->m_device, 1, &writeInfo, 0, nullptr);
-
- _setBinding(Binding::Type::BufferResource, range, index, buffer);
-}
-
-void VKRenderer::DescriptorSetImpl::setResource(UInt range, UInt index, ResourceView* view)
-{
- auto viewImpl = (ResourceViewImpl*)view;
- switch (viewImpl->m_type)
- {
- case ResourceViewImpl::ViewType::Texture:
- {
- auto textureViewImpl = (TextureResourceViewImpl*)viewImpl;
- VkDescriptorImageInfo imageInfo = {};
- imageInfo.imageView = textureViewImpl->m_view;
- imageInfo.imageLayout = textureViewImpl->m_layout;
- // imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
-
- VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
- writeInfo.dstBinding = uint32_t(range);
- writeInfo.dstArrayElement = uint32_t(index);
- writeInfo.descriptorCount = 1;
- writeInfo.descriptorType = m_layout->m_ranges[range].descriptorType;
- writeInfo.pImageInfo = &imageInfo;
-
- m_renderer->m_api.vkUpdateDescriptorSets(m_renderer->m_device, 1, &writeInfo, 0, nullptr);
- }
- break;
-
- case ResourceViewImpl::ViewType::TexelBuffer:
- {
- auto bufferViewImpl = (TexelBufferResourceViewImpl*)viewImpl;
-
- VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
- writeInfo.dstBinding = uint32_t(range);
- writeInfo.dstArrayElement = uint32_t(index);
- writeInfo.descriptorCount = 1;
- writeInfo.descriptorType = m_layout->m_ranges[range].descriptorType;
- writeInfo.pTexelBufferView = &bufferViewImpl->m_view;
-
- m_renderer->m_api.vkUpdateDescriptorSets(m_renderer->m_device, 1, &writeInfo, 0, nullptr);
- }
- break;
-
- case ResourceViewImpl::ViewType::PlainBuffer:
- {
- auto bufferViewImpl = (PlainBufferResourceViewImpl*) viewImpl;
-
- VkDescriptorBufferInfo bufferInfo = {};
- bufferInfo.buffer = bufferViewImpl->m_buffer->m_buffer.m_buffer;
- bufferInfo.offset = bufferViewImpl->offset;
- bufferInfo.range = bufferViewImpl->size;
-
- VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
- writeInfo.dstBinding = uint32_t(range);
- writeInfo.dstArrayElement = uint32_t(index);
- writeInfo.descriptorCount = 1;
- writeInfo.descriptorType = m_layout->m_ranges[range].descriptorType;
- writeInfo.pBufferInfo = &bufferInfo;
-
- m_renderer->m_api.vkUpdateDescriptorSets(m_renderer->m_device, 1, &writeInfo, 0, nullptr);
- }
- break;
-
- }
-
- _setBinding(Binding::Type::ResourceView, range, index, view);
-}
-
-void VKRenderer::DescriptorSetImpl::setSampler(UInt range, UInt index, SamplerState* sampler)
-{
-
- _setBinding(Binding::Type::SamplerState, range, index, sampler);
-}
-
-void VKRenderer::DescriptorSetImpl::setCombinedTextureSampler(
- UInt range,
- UInt index,
- ResourceView* textureView,
- SamplerState* sampler)
-{
-
- _setBinding(Binding::Type::SamplerState, range, index, sampler);
- _setBinding(Binding::Type::ResourceView, range, index, textureView);
-}
-
-void VKRenderer::setDescriptorSet(PipelineType pipelineType, PipelineLayout* layout, UInt index, DescriptorSet* descriptorSet)
-{
- // Ideally this should eventually be as simple as:
- //
- // m_api.vkCmdBindDescriptorSets(
- // commandBuffer,
- // translatePipelineBindPoint(pipelineType),
- // layout->m_pipelineLayout,
- // index,
- // 1,
- // ((DescriptorSetImpl*) descriptorSet)->m_descriptorSet,
- // 0,
- // nullptr);
- //
- // For now we are lazily flushing state right before drawing, so
- // we will hang onto the parameters that were passed in and then
- // use them later.
- //
-
- auto descriptorSetImpl = (DescriptorSetImpl*)descriptorSet;
- m_currentDescriptorSetImpls[index] = descriptorSetImpl;
- m_currentDescriptorSets[index] = descriptorSetImpl->m_descriptorSet;
-}
-
-Result VKRenderer::createProgram(const ShaderProgram::Desc& desc, ShaderProgram** outProgram)
-{
- RefPtr<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]);
- }
- *outProgram = impl.detach();
- return SLANG_OK;
-}
-
-Result VKRenderer::createGraphicsPipelineState(const GraphicsPipelineStateDesc& desc, PipelineState** outState)
-{
- VkPipelineCache pipelineCache = VK_NULL_HANDLE;
-
- auto programImpl = (ShaderProgramImpl*) desc.program;
- auto pipelineLayoutImpl = (PipelineLayoutImpl*) desc.pipelineLayout;
- auto inputLayoutImpl = (InputLayoutImpl*) desc.inputLayout;
-
- const int width = int(desc.framebufferWidth);
- const int height = int(desc.framebufferHeight);
-
- // Shader Stages
- //
- // Currently only handles vertex/fragment.
-
- static const uint32_t kMaxShaderStages = 2;
- VkPipelineShaderStageCreateInfo shaderStages[kMaxShaderStages];
-
- uint32_t shaderStageCount = 0;
- shaderStages[shaderStageCount++] = programImpl->m_vertex;
- shaderStages[shaderStageCount++] = programImpl->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 (inputLayoutImpl)
- {
- vertexInputBindingDescription.binding = 0;
- vertexInputBindingDescription.stride = inputLayoutImpl->m_vertexSize;
- vertexInputBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
-
- const auto& srcAttributeDescs = inputLayoutImpl->m_vertexDescs;
-
- vertexInputInfo.vertexBindingDescriptionCount = 1;
- vertexInputInfo.pVertexBindingDescriptions = &vertexInputBindingDescription;
-
- vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(srcAttributeDescs.getCount());
- vertexInputInfo.pVertexAttributeDescriptions = srcAttributeDescs.getBuffer();
- }
-
- 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 = pipelineLayoutImpl->m_pipelineLayout;
- pipelineInfo.renderPass = m_renderPass;
- pipelineInfo.subpass = 0;
- pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
-
- VkPipeline pipeline = VK_NULL_HANDLE;
- SLANG_VK_CHECK(m_api.vkCreateGraphicsPipelines(m_device, pipelineCache, 1, &pipelineInfo, nullptr, &pipeline));
-
- RefPtr<PipelineStateImpl> pipelineStateImpl = new PipelineStateImpl(m_api);
- pipelineStateImpl->m_pipeline = pipeline;
- pipelineStateImpl->m_pipelineLayout = pipelineLayoutImpl;
- pipelineStateImpl->m_shaderProgram = programImpl;
- *outState = pipelineStateImpl.detach();
- return SLANG_OK;
-}
-
-Result VKRenderer::createComputePipelineState(const ComputePipelineStateDesc& desc, PipelineState** outState)
-{
- VkPipelineCache pipelineCache = VK_NULL_HANDLE;
-
- auto programImpl = (ShaderProgramImpl*) desc.program;
- auto pipelineLayoutImpl = (PipelineLayoutImpl*) desc.pipelineLayout;
-
- VkComputePipelineCreateInfo computePipelineInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
- computePipelineInfo.stage = programImpl->m_compute;
- computePipelineInfo.layout = pipelineLayoutImpl->m_pipelineLayout;
-
- VkPipeline pipeline = VK_NULL_HANDLE;
- SLANG_VK_CHECK(m_api.vkCreateComputePipelines(m_device, pipelineCache, 1, &computePipelineInfo, nullptr, &pipeline));
-
- RefPtr<PipelineStateImpl> pipelineStateImpl = new PipelineStateImpl(m_api);
- pipelineStateImpl->m_pipeline = pipeline;
- pipelineStateImpl->m_pipelineLayout = pipelineLayoutImpl;
- pipelineStateImpl->m_shaderProgram = programImpl;
- *outState = pipelineStateImpl.detach();
- return SLANG_OK;
-}
-
-
-#if 0
- else if (m_currentProgram->m_pipelineType == PipelineType::Graphics)
- {
- // Create the graphics pipeline
-
- const int width = m_swapChain.getWidth();
- const int height = m_swapChain.getHeight();
-
-
-
-
-
- //
-
-
- }
- else
- {
- assert(!"Unhandled program type");
- return SLANG_FAIL;
- }
-
- pipelineOut = pipeline;
- return SLANG_OK;
-
-
-#endif
-
-} // renderer_test