summaryrefslogtreecommitdiffstats
path: root/tools/render-test
diff options
context:
space:
mode:
Diffstat (limited to 'tools/render-test')
-rw-r--r--tools/render-test/circular-resource-heap-d3d12.cpp222
-rw-r--r--tools/render-test/circular-resource-heap-d3d12.h206
-rw-r--r--tools/render-test/d3d-util.cpp306
-rw-r--r--tools/render-test/d3d-util.h61
-rw-r--r--tools/render-test/descriptor-heap-d3d12.cpp47
-rw-r--r--tools/render-test/descriptor-heap-d3d12.h115
-rw-r--r--tools/render-test/options.h4
-rw-r--r--tools/render-test/png-serialize-util.h6
-rw-r--r--tools/render-test/render-d3d11.cpp1101
-rw-r--r--tools/render-test/render-d3d11.h10
-rw-r--r--tools/render-test/render-d3d12.cpp2467
-rw-r--r--tools/render-test/render-d3d12.h10
-rw-r--r--tools/render-test/render-gl.cpp1049
-rw-r--r--tools/render-test/render-gl.h10
-rw-r--r--tools/render-test/render-test.vcxproj42
-rw-r--r--tools/render-test/render-test.vcxproj.filters93
-rw-r--r--tools/render-test/render-vk.cpp2019
-rw-r--r--tools/render-test/render-vk.h10
-rw-r--r--tools/render-test/render.cpp390
-rw-r--r--tools/render-test/render.h583
-rw-r--r--tools/render-test/resource-d3d12.cpp214
-rw-r--r--tools/render-test/resource-d3d12.h178
-rw-r--r--tools/render-test/shader-input-layout.h2
-rw-r--r--tools/render-test/surface.cpp222
-rw-r--r--tools/render-test/surface.h86
-rw-r--r--tools/render-test/vk-api.cpp138
-rw-r--r--tools/render-test/vk-api.h196
-rw-r--r--tools/render-test/vk-device-queue.cpp199
-rw-r--r--tools/render-test/vk-device-queue.h94
-rw-r--r--tools/render-test/vk-module.cpp76
-rw-r--r--tools/render-test/vk-module.h39
-rw-r--r--tools/render-test/vk-swap-chain.cpp421
-rw-r--r--tools/render-test/vk-swap-chain.h141
-rw-r--r--tools/render-test/vk-util.cpp59
-rw-r--r--tools/render-test/vk-util.h41
-rw-r--r--tools/render-test/window.h10
36 files changed, 16 insertions, 10851 deletions
diff --git a/tools/render-test/circular-resource-heap-d3d12.cpp b/tools/render-test/circular-resource-heap-d3d12.cpp
deleted file mode 100644
index ae8e13822..000000000
--- a/tools/render-test/circular-resource-heap-d3d12.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-#include "circular-resource-heap-d3d12.h"
-
-namespace renderer_test {
-using namespace Slang;
-
-D3D12CircularResourceHeap::D3D12CircularResourceHeap():
- m_fence(nullptr),
- m_device(nullptr),
- m_blockFreeList(sizeof(Block), SLANG_ALIGN_OF(Block), 16),
- m_blocks(nullptr)
-{
- m_back.m_block = nullptr;
- m_back.m_position = nullptr;
- m_front.m_block = nullptr;
- m_front.m_position = nullptr;
-}
-
-D3D12CircularResourceHeap::~D3D12CircularResourceHeap()
-{
- _freeBlockListResources(m_blocks);
-}
-
-void D3D12CircularResourceHeap::_freeBlockListResources(const Block* start)
-{
- if (start)
- {
- const Block* block = start;
- do
- {
- ID3D12Resource* resource = block->m_resource;
-
- resource->Unmap(0, nullptr);
- resource->Release();
-
- // Next in list
- block = block->m_next;
-
- } while (block != start);
- }
-}
-
-Result D3D12CircularResourceHeap::init(ID3D12Device* device, const Desc& desc, D3D12CounterFence* fence)
-{
- assert(m_blocks == nullptr);
- assert(desc.m_blockSize > 0);
-
- m_fence = fence;
- m_desc = desc;
- m_device = device;
-
- return SLANG_OK;
-}
-
-void D3D12CircularResourceHeap::addSync(uint64_t signalValue)
-{
- assert(signalValue == m_fence->getCurrentValue());
- PendingEntry entry;
- entry.m_completedValue = signalValue;
- entry.m_cursor = m_front;
- m_pendingQueue.Add(entry);
-}
-
-void D3D12CircularResourceHeap::updateCompleted()
-{
- const uint64_t completedValue = m_fence->getCompletedValue();
-
-#if 0
- while (m_pendingQueue.Count() != 0)
- {
- const PendingEntry& entry = m_pendingQueue[0];
- if (entry.m_completedValue <= completedValue)
- {
- m_back = entry.m_cursor;
- m_pendingQueue.RemoveAt(0);
- }
- else
- {
- break;
- }
- }
-#else
- // A more efficient implementation is m_pendingQueue is implemented as a vector like type
- const int size = int(m_pendingQueue.Count());
- int end = 0;
- while (end < size && m_pendingQueue[end].m_completedValue <= completedValue)
- {
- end++;
- }
-
- if (end > 0)
- {
- // Set the back position
- m_back = m_pendingQueue[end - 1].m_cursor;
- if (end == size)
- {
- m_pendingQueue.Clear();
- }
- else
- {
- m_pendingQueue.RemoveRange(0, size);
- }
- }
-#endif
-}
-
-D3D12CircularResourceHeap::Block* D3D12CircularResourceHeap::_newBlock()
-{
- D3D12_RESOURCE_DESC desc;
-
- desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
- desc.Alignment = 0;
- desc.Width = m_desc.m_blockSize;
- desc.Height = 1;
- desc.DepthOrArraySize = 1;
- desc.MipLevels = 1;
- desc.Format = DXGI_FORMAT_UNKNOWN;
- desc.SampleDesc.Count = 1;
- desc.SampleDesc.Quality = 0;
- desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
- desc.Flags = D3D12_RESOURCE_FLAG_NONE;
-
- ComPtr<ID3D12Resource> resource;
- Result res = m_device->CreateCommittedResource(&m_desc.m_heapProperties, m_desc.m_heapFlags, &desc, m_desc.m_initialState, nullptr, IID_PPV_ARGS(resource.writeRef()));
- if (SLANG_FAILED(res))
- {
- assert(!"Resource allocation failed");
- return nullptr;
- }
-
- uint8_t* data = nullptr;
- if (m_desc.m_heapProperties.Type == D3D12_HEAP_TYPE_READBACK)
- {
- }
- else
- {
- // Map it, and keep it mapped
- resource->Map(0, nullptr, (void**)&data);
- }
-
- // We have no blocks -> so lets allocate the first
- Block* block = (Block*)m_blockFreeList.allocate();
- block->m_next = nullptr;
-
- block->m_resource = resource.detach();
- block->m_start = data;
- return block;
-}
-
-D3D12CircularResourceHeap::Cursor D3D12CircularResourceHeap::allocate(size_t size, size_t alignment)
-{
- const size_t blockSize = getBlockSize();
-
- assert(size <= blockSize);
-
- // If nothing is allocated add the first block
- if (m_blocks == nullptr)
- {
- Block* block = _newBlock();
- if (!block)
- {
- Cursor cursor = {};
- return cursor;
- }
- m_blocks = block;
- // Make circular
- block->m_next = block;
-
- // Point front and back to same position, as currently it is all free
- m_back = { block, block->m_start };
- m_front = m_back;
- }
-
- // If front and back are in the same block then front MUST be ahead of back (as that defined as
- // an invariant and is required for block insertion to be possible
- Block* block = m_front.m_block;
-
- // Check the invariant
- assert(block != m_back.m_block || m_front.m_position >= m_back.m_position);
-
- {
- uint8_t* cur = (uint8_t*)((size_t(m_front.m_position) + alignment - 1) & ~(alignment - 1));
- // Does the the allocation fit?
- if (cur + size <= block->m_start + blockSize)
- {
- // It fits
- // Move the front forward
- m_front.m_position = cur + size;
- Cursor cursor = { block, cur };
- return cursor;
- }
- }
-
- // Okay I can't fit into current block...
-
- // If the next block contains front, we need to add a block, else we can use that block
- if (block->m_next == m_back.m_block)
- {
- Block* newBlock = _newBlock();
- // Insert into the list
- newBlock->m_next = block->m_next;
- block->m_next = newBlock;
- }
-
- // Use the block we are going to add to
- block = block->m_next;
- uint8_t* cur = (uint8_t*)((size_t(block->m_start) + alignment - 1) & ~(alignment - 1));
- // Does the the allocation fit?
- if (cur + size > block->m_start + blockSize)
- {
- assert(!"Couldn't fit into a free block(!) Alignment breaks it?");
- Cursor cursor = {};
- return cursor;
- }
- // It fits
- // Move the front forward
- m_front.m_block = block;
- m_front.m_position = cur + size;
- Cursor cursor = { block, cur };
- return cursor;
-}
-
-} // namespace renderer_test
diff --git a/tools/render-test/circular-resource-heap-d3d12.h b/tools/render-test/circular-resource-heap-d3d12.h
deleted file mode 100644
index baa9a9b0c..000000000
--- a/tools/render-test/circular-resource-heap-d3d12.h
+++ /dev/null
@@ -1,206 +0,0 @@
-#pragma once
-
-#include "../../slang-com-ptr.h"
-#include "../../source/core/list.h"
-#include "../../source/core/slang-free-list.h"
-
-#include "resource-d3d12.h"
-
-namespace renderer_test {
-
-/*! \brief The D3D12CircularResourceHeap is a heap that is suited for size constrained real-time resources allocation that
-is transitory in nature. It is designed to allocate resources which are used and discarded, often used where in
-previous versions of DirectX the 'DISCARD' flag was used.
-
-The idea is to have a heap which chunks of resource can be allocated, and used for GPU execution,
-and that the heap is able through the addSync/updateCompleted idiom is able to track when the usage of the resources is
-completed allowing them to be reused. The heap is arranged as circularly, with new allocations made from the front, and the back
-being updated as the GPU updating the back when it is informed anything using prior parts of the heap have completed. In this
-arrangement all the heap between the back and the front can be thought of as in use or potentially in use by the GPU. All the heap
-from the front back around to the back, is free and can be allocated from. It is the responsibility of the user of the Heap to make
-sure the invariant holds, but in most normal usage it does so simply.
-
-Another feature of the heap is that it does not require upfront knowledge of how big a heap is needed. The backing resources will be expanded
-dynamically with requests as needed. The only requirement is that know single request can be larger than m_blockSize specified in the Desc
-used to initialize the heap. This is because all the backing resources are allocated to a single size. This limitation means the D3D12CircularResourceHeap
-may not be the best use for example for uploading a texture - because it's design is really around transitory uploads or write backs, and so more suited
-to constant buffers, vertex buffer, index buffers and the like.
-
-To upload a texture at program startup it is most likely better to use a D3D12ResourceScopeManager.
-
-\code{.cpp}
-
-typedef D3D12CircularResourceHeap Heap;
-
-Heap::Cursor cursor = heap.allocateVertexBuffer(sizeof(Vertex) * numVerts);
-Memory:copy(cursor.m_position, verts, sizeof(Vertex) * numVerts);
-
-// Do a command using the GPU handle
-m_commandList->...
-// Do another command using the GPU handle
-
-m_commandList->...
-
-// Execute the command list on the command queue
-{
- ID3D12CommandList* lists[] = { m_commandList };
- m_commandQueue->ExecuteCommandLists(SLANG_COUNT_OF(lists), lists);
-}
-
-// Add a sync point
-const uint64_t signalValue = m_fence.nextSignal(m_commandQueue);
-heap.addSync(signalValue)
-
-// The cursors cannot be used anymore
-
-// At some later point call updateCompleted. This will see where the GPU is at, and make resources available that the GPU no longer accesses.
-heap.updateCompleted();
-
-\endcode
-
-### Implementation
-
-Front and back can be in the same block, but ONLY if back is behind front, because we have to always be able to insert
-new blocks in front of front. So it must be possible to do an block insertion between the two of them.
-
-|--B---F-----| |----------|
-
-When B and F are on top of one another it means there is nothing in the list. NOTE this also means that a move of front can never place it
-top of the back.
-
-https://msdn.microsoft.com/en-us/library/windows/desktop/dn899125%28v=vs.85%29.aspx
-https://msdn.microsoft.com/en-us/library/windows/desktop/mt426646%28v=vs.85%29.aspx
-*/
-
-class D3D12CircularResourceHeap
-{
- protected:
- struct Block;
- public:
- typedef D3D12CircularResourceHeap ThisType;
-
- /// The alignment used for VERTEX_BUFFER allocations
- /// Strictly speaking it seems the hardware can handle 4 byte alignment, but since often in use
- /// data will be copied from CPU memory to the allocation, using 16 byte alignment is superior as allows
- /// significantly faster memcpy.
- /// The sample that shows sizeof(float) - 4 bytes is appropriate is at the link below.
- /// https://msdn.microsoft.com/en-us/library/windows/desktop/mt426646%28v=vs.85%29.aspx
- enum
- {
- VERTEX_BUFFER_ALIGNMENT = 16,
- };
-
- struct Desc
- {
- void init()
- {
- {
- D3D12_HEAP_PROPERTIES& props = m_heapProperties;
-
- props.Type = D3D12_HEAP_TYPE_UPLOAD;
- props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- props.CreationNodeMask = 1;
- props.VisibleNodeMask = 1;
- }
- m_heapFlags = D3D12_HEAP_FLAG_NONE;
- m_initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
- m_blockSize = 0;
- }
-
- D3D12_HEAP_PROPERTIES m_heapProperties;
- D3D12_HEAP_FLAGS m_heapFlags;
- D3D12_RESOURCE_STATES m_initialState;
- size_t m_blockSize;
- };
-
- /// Cursor position
- struct Cursor
- {
- /// Get GpuHandle
- SLANG_FORCE_INLINE D3D12_GPU_VIRTUAL_ADDRESS getGpuHandle() const { return m_block->m_resource->GetGPUVirtualAddress() + size_t(m_position - m_block->m_start); }
- /// Must have a block and position
- SLANG_FORCE_INLINE bool isValid() const { return m_block != nullptr; }
- /// Calculate the offset into the underlying resource
- SLANG_FORCE_INLINE size_t getOffset() const { return size_t(m_position - m_block->m_start); }
- /// Get the underlying resource
- SLANG_FORCE_INLINE ID3D12Resource* getResource() const { return m_block->m_resource; }
-
- Block* m_block; ///< The block index
- uint8_t* m_position; ///< The current position
- };
-
- /// Get the desc used to initialize the heap
- SLANG_FORCE_INLINE const Desc& getDesc() const { return m_desc; }
-
- /// Must be called before used
- /// Block size must be at least as large as the _largest_ thing allocated
- /// Also note depending on alignment of a resource allocation, the block size might also need to take into account the
- /// maximum alignment use. It is a REQUIREMENT that a newly allocated resource block is large enough to hold any
- /// allocation taking into account the alignment used.
- Slang::Result init(ID3D12Device* device, const Desc& desc, D3D12CounterFence* fence);
-
- /// Get the block size
- SLANG_FORCE_INLINE size_t getBlockSize() const { return m_desc.m_blockSize; }
-
- /// Allocate constant buffer of specified size
- Cursor allocate(size_t size, size_t alignment);
-
- /// Allocate a constant buffer
- SLANG_FORCE_INLINE Cursor allocateConstantBuffer(size_t size) { return allocate(size, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT); }
- /// Allocate a vertex buffer
- SLANG_FORCE_INLINE Cursor allocateVertexBuffer(size_t size) { return allocate(size, VERTEX_BUFFER_ALIGNMENT); }
-
- /// Create filled in constant buffer
- SLANG_FORCE_INLINE Cursor newConstantBuffer(const void* data, size_t size) { Cursor cursor = allocateConstantBuffer(size); ::memcpy(cursor.m_position, data, size); return cursor; }
- /// Create in filled in constant buffer
- template <typename T>
- SLANG_FORCE_INLINE Cursor newConstantBuffer(const T& in) { return newConstantBuffer(&in, sizeof(T)); }
-
- /// Look where the GPU has got to and release anything not currently used
- void updateCompleted();
- /// Add a sync point - meaning that when this point is hit in the queue
- /// all of the resources up to this point will no longer be used.
- void addSync(uint64_t signalValue);
-
- /// Get the gpu address of this cursor
- D3D12_GPU_VIRTUAL_ADDRESS getGpuHandle(const Cursor& cursor) const { return cursor.m_block->m_resource->GetGPUVirtualAddress() + size_t(cursor.m_position - cursor.m_block->m_start); }
-
- /// Ctor
- D3D12CircularResourceHeap();
- /// Dtor
- ~D3D12CircularResourceHeap();
-
- protected:
-
- struct Block
- {
- ID3D12Resource* m_resource; ///< The mapped resource
- uint8_t* m_start; ///< Once created the resource is mapped to here
- Block* m_next; ///< Points to next block in the list
- };
- struct PendingEntry
- {
- uint64_t m_completedValue; ///< The value when this is completed
- Cursor m_cursor; ///< the cursor at that point
- };
- void _freeBlockListResources(const Block* block);
- /// Create a new block (with associated resource), do not add the block list
- Block* _newBlock();
-
- Block* m_blocks; ///< Circular singly linked list of block. nullptr initially
- Slang::FreeList m_blockFreeList; ///< Free list of actual allocations of blocks
- Slang::List<PendingEntry> m_pendingQueue; ///< Holds the list of pending positions. When the fence value is greater than the value on the queue entry, the entry is done.
-
- // Allocation is made from the front, and freed from the back.
- Cursor m_back; ///< Current back position.
- Cursor m_front; ///< Current front position.
-
- Desc m_desc; ///< Describes the heap
-
- D3D12CounterFence* m_fence; ///< The fence to use
- ID3D12Device* m_device; ///< The device that resources will be constructed on
-};
-
-} // namespace renderer_test
-
diff --git a/tools/render-test/d3d-util.cpp b/tools/render-test/d3d-util.cpp
deleted file mode 100644
index 08aa563ca..000000000
--- a/tools/render-test/d3d-util.cpp
+++ /dev/null
@@ -1,306 +0,0 @@
-// d3d-util.cpp
-#include "d3d-util.h"
-
-#include <d3dcompiler.h>
-
-// We will use the C standard library just for printing error messages.
-#include <stdio.h>
-
-namespace renderer_test {
-using namespace Slang;
-
-/* static */D3D_PRIMITIVE_TOPOLOGY D3DUtil::getPrimitiveTopology(PrimitiveTopology topology)
-{
- switch (topology)
- {
- case PrimitiveTopology::TriangleList:
- {
- return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
- }
- default: break;
- }
- return D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
-}
-
-/* static */DXGI_FORMAT D3DUtil::getMapFormat(Format format)
-{
- switch (format)
- {
- case Format::RGBA_Float32: return DXGI_FORMAT_R32G32B32A32_FLOAT;
- case Format::RGB_Float32: return DXGI_FORMAT_R32G32B32_FLOAT;
- case Format::RG_Float32: return DXGI_FORMAT_R32G32_FLOAT;
- case Format::R_Float32: return DXGI_FORMAT_R32_FLOAT;
- case Format::RGBA_Unorm_UInt8: return DXGI_FORMAT_R8G8B8A8_UNORM;
- case Format::R_UInt32: return DXGI_FORMAT_R32_UINT;
-
- case Format::D_Float32: return DXGI_FORMAT_D32_FLOAT;
- case Format::D_Unorm24_S8: return DXGI_FORMAT_D24_UNORM_S8_UINT;
-
- default: return DXGI_FORMAT_UNKNOWN;
- }
-}
-
-/* static */DXGI_FORMAT D3DUtil::calcResourceFormat(UsageType usage, Int usageFlags, DXGI_FORMAT format)
-{
- SLANG_UNUSED(usage);
- if (usageFlags)
- {
- switch (format)
- {
- case DXGI_FORMAT_R32_FLOAT: /* fallthru */
- case DXGI_FORMAT_R32_UINT:
- case DXGI_FORMAT_D32_FLOAT:
- {
- return DXGI_FORMAT_R32_TYPELESS;
- }
- case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24G8_TYPELESS;
- default: break;
- }
- return format;
- }
- return format;
-}
-
-/* static */DXGI_FORMAT D3DUtil::calcFormat(UsageType usage, DXGI_FORMAT format)
-{
- switch (usage)
- {
- case USAGE_COUNT_OF:
- case USAGE_UNKNOWN:
- {
- return DXGI_FORMAT_UNKNOWN;
- }
- case USAGE_DEPTH_STENCIL:
- {
- switch (format)
- {
- case DXGI_FORMAT_D32_FLOAT: /* fallthru */
- case DXGI_FORMAT_R32_TYPELESS:
- {
- return DXGI_FORMAT_D32_FLOAT;
- }
- case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: return DXGI_FORMAT_D24_UNORM_S8_UINT;
- case DXGI_FORMAT_R24G8_TYPELESS: return DXGI_FORMAT_D24_UNORM_S8_UINT;
- default: break;
- }
- return format;
- }
- case USAGE_TARGET:
- {
- switch (format)
- {
- case DXGI_FORMAT_D32_FLOAT: /* fallthru */
- case DXGI_FORMAT_D24_UNORM_S8_UINT:
- {
- return DXGI_FORMAT_UNKNOWN;
- }
- case DXGI_FORMAT_R32_TYPELESS: return DXGI_FORMAT_R32_FLOAT;
- default: break;
- }
- return format;
- }
- case USAGE_SRV:
- {
- switch (format)
- {
- case DXGI_FORMAT_D32_FLOAT: /* fallthru */
- case DXGI_FORMAT_R32_TYPELESS:
- {
- return DXGI_FORMAT_R32_FLOAT;
- }
- case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
- default: break;
- }
-
- return format;
- }
- }
-
- assert(!"Not reachable");
- return DXGI_FORMAT_UNKNOWN;
-}
-
-bool D3DUtil::isTypeless(DXGI_FORMAT format)
-{
- switch (format)
- {
- case DXGI_FORMAT_R32G32B32A32_TYPELESS:
- case DXGI_FORMAT_R32G32B32_TYPELESS:
- case DXGI_FORMAT_R16G16B16A16_TYPELESS:
- case DXGI_FORMAT_R32G32_TYPELESS:
- case DXGI_FORMAT_R32G8X24_TYPELESS:
- case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
- case DXGI_FORMAT_R10G10B10A2_TYPELESS:
- case DXGI_FORMAT_R8G8B8A8_TYPELESS:
- case DXGI_FORMAT_R16G16_TYPELESS:
- case DXGI_FORMAT_R32_TYPELESS:
- case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
- case DXGI_FORMAT_R24G8_TYPELESS:
- case DXGI_FORMAT_R8G8_TYPELESS:
- case DXGI_FORMAT_R16_TYPELESS:
- case DXGI_FORMAT_R8_TYPELESS:
- case DXGI_FORMAT_BC1_TYPELESS:
- case DXGI_FORMAT_BC2_TYPELESS:
- case DXGI_FORMAT_BC3_TYPELESS:
- case DXGI_FORMAT_BC4_TYPELESS:
- case DXGI_FORMAT_BC5_TYPELESS:
- case DXGI_FORMAT_B8G8R8A8_TYPELESS:
- case DXGI_FORMAT_BC6H_TYPELESS:
- case DXGI_FORMAT_BC7_TYPELESS:
- {
- return true;
- }
- default: break;
- }
- return false;
-}
-
-/* static */Int D3DUtil::getNumColorChannelBits(DXGI_FORMAT fmt)
-{
- switch (fmt)
- {
- case DXGI_FORMAT_R32G32B32A32_TYPELESS:
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- case DXGI_FORMAT_R32G32B32A32_UINT:
- case DXGI_FORMAT_R32G32B32A32_SINT:
- case DXGI_FORMAT_R32G32B32_TYPELESS:
- case DXGI_FORMAT_R32G32B32_FLOAT:
- case DXGI_FORMAT_R32G32B32_UINT:
- case DXGI_FORMAT_R32G32B32_SINT:
- {
- return 32;
- }
- case DXGI_FORMAT_R16G16B16A16_TYPELESS:
- case DXGI_FORMAT_R16G16B16A16_FLOAT:
- case DXGI_FORMAT_R16G16B16A16_UNORM:
- case DXGI_FORMAT_R16G16B16A16_UINT:
- case DXGI_FORMAT_R16G16B16A16_SNORM:
- case DXGI_FORMAT_R16G16B16A16_SINT:
- {
- return 16;
- }
- case DXGI_FORMAT_R10G10B10A2_TYPELESS:
- case DXGI_FORMAT_R10G10B10A2_UNORM:
- case DXGI_FORMAT_R10G10B10A2_UINT:
- case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
- {
- return 10;
- }
- case DXGI_FORMAT_R8G8B8A8_TYPELESS:
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
- case DXGI_FORMAT_R8G8B8A8_UINT:
- case DXGI_FORMAT_R8G8B8A8_SNORM:
- case DXGI_FORMAT_R8G8B8A8_SINT:
- case DXGI_FORMAT_B8G8R8A8_UNORM:
- case DXGI_FORMAT_B8G8R8X8_UNORM:
- case DXGI_FORMAT_B8G8R8A8_TYPELESS:
- case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
- case DXGI_FORMAT_B8G8R8X8_TYPELESS:
- case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
- {
- return 8;
- }
- case DXGI_FORMAT_B5G6R5_UNORM:
- case DXGI_FORMAT_B5G5R5A1_UNORM:
- {
- return 5;
- }
- case DXGI_FORMAT_B4G4R4A4_UNORM:
- return 4;
-
- default:
- return 0;
- }
-}
-
-// Note: this subroutine is now only used by D3D11 for generating bytecode to go into input layouts.
-//
-// TODO: we can probably remove that code completely by switching to a PSO-like model across all APIs.
-//
-/* static */Result D3DUtil::compileHLSLShader(char const* sourcePath, char const* source, char const* entryPointName, char const* dxProfileName, ComPtr<ID3DBlob>& shaderBlobOut)
-{
- // Rather than statically link against the `d3dcompile` library, we
- // dynamically load it.
- //
- // Note: A more realistic application would compile from HLSL text to D3D
- // shader bytecode as part of an offline process, rather than doing it
- // on-the-fly like this
- //
- static pD3DCompile compileFunc = nullptr;
- if (!compileFunc)
- {
- // TODO(tfoley): maybe want to search for one of a few versions of the DLL
- HMODULE compilerModule = LoadLibraryA("d3dcompiler_47.dll");
- if (!compilerModule)
- {
- fprintf(stderr, "error: failed load 'd3dcompiler_47.dll'\n");
- return SLANG_FAIL;
- }
-
- compileFunc = (pD3DCompile)GetProcAddress(compilerModule, "D3DCompile");
- if (!compileFunc)
- {
- fprintf(stderr, "error: failed load symbol 'D3DCompile'\n");
- return SLANG_FAIL;
- }
- }
-
- // For this example, we turn on debug output, and turn off all
- // optimization. A real application would only use these flags
- // when shader debugging is needed.
- UINT flags = 0;
- flags |= D3DCOMPILE_DEBUG;
- flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0 | D3DCOMPILE_SKIP_OPTIMIZATION;
-
- // We will always define `__HLSL__` when compiling here, so that
- // input code can react differently to being compiled as pure HLSL.
- D3D_SHADER_MACRO defines[] = {
- { "__HLSL__", "1" },
- { nullptr, nullptr },
- };
-
- // The `D3DCompile` entry point takes a bunch of parameters, but we
- // don't really need most of them for Slang-generated code.
- ComPtr<ID3DBlob> shaderBlob;
- ComPtr<ID3DBlob> errorBlob;
-
- HRESULT hr = compileFunc(source, strlen(source), sourcePath, &defines[0], nullptr, entryPointName, dxProfileName, flags, 0,
- shaderBlob.writeRef(), errorBlob.writeRef());
-
- // If the HLSL-to-bytecode compilation produced any diagnostic messages
- // then we will print them out (whether or not the compilation failed).
- if (errorBlob)
- {
- ::fputs((const char*)errorBlob->GetBufferPointer(), stderr);
- ::fflush(stderr);
- ::OutputDebugStringA((const char*)errorBlob->GetBufferPointer());
- }
-
- SLANG_RETURN_ON_FAIL(hr);
- shaderBlobOut.swap(shaderBlob);
- return SLANG_OK;
-}
-
-/* static */void D3DUtil::appendWideChars(const char* in, List<wchar_t>& out)
-{
- size_t len = ::strlen(in);
-
- const DWORD dwFlags = 0;
- int outSize = ::MultiByteToWideChar(CP_UTF8, dwFlags, in, int(len), nullptr, 0);
-
- if (outSize > 0)
- {
- const UInt prevSize = out.Count();
- out.SetSize(prevSize + len + 1);
-
- WCHAR* dst = out.Buffer() + prevSize;
- ::MultiByteToWideChar(CP_UTF8, dwFlags, in, int(len), dst, outSize);
- // Make null terminated
- dst[outSize] = 0;
- // Remove terminating 0 from array
- out.UnsafeShrinkToSize(prevSize + outSize);
- }
-}
-
-} // renderer_test
diff --git a/tools/render-test/d3d-util.h b/tools/render-test/d3d-util.h
deleted file mode 100644
index b7a268fd8..000000000
--- a/tools/render-test/d3d-util.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// d3d-util.h
-#pragma once
-
-#include <stdint.h>
-
-#include "../../slang-com-helper.h"
-
-#include "../../slang-com-ptr.h"
-#include "../../source/core/list.h"
-
-#include "render.h"
-
-#include <D3Dcommon.h>
-#include <DXGIFormat.h>
-
-namespace renderer_test {
-
-class D3DUtil
-{
- public:
- enum UsageType
- {
- USAGE_UNKNOWN, ///< Generally used to mark an error
- USAGE_TARGET, ///< Format should be used when written as target
- USAGE_DEPTH_STENCIL, ///< Format should be used when written as depth stencil
- USAGE_SRV, ///< Format if being read as srv
- USAGE_COUNT_OF,
- };
- enum UsageFlag
- {
- USAGE_FLAG_MULTI_SAMPLE = 0x1, ///< If set will be used form multi sampling (such as MSAA)
- USAGE_FLAG_SRV = 0x2, ///< If set means will be used as a shader resource view (SRV)
- };
-
- /// Get primitive topology as D3D primitive topology
- static D3D_PRIMITIVE_TOPOLOGY getPrimitiveTopology(PrimitiveTopology prim);
-
- /// Calculate size taking into account alignment. Alignment must be a power of 2
- static UInt calcAligned(UInt size, UInt alignment) { return (size + alignment - 1) & ~(alignment - 1); }
-
- /// Compile HLSL code to DXBC
- static Slang::Result compileHLSLShader(char const* sourcePath, char const* source, char const* entryPointName, char const* dxProfileName, Slang::ComPtr<ID3DBlob>& shaderBlobOut);
-
- /// Given a slang pixel format returns the equivalent DXGI_ pixel format. If the format is not known, will return DXGI_FORMAT_UNKNOWN
- static DXGI_FORMAT getMapFormat(Format format);
-
- /// Given the usage, flags, and format will return the most suitable format. Will return DXGI_UNKNOWN if combination is not possible
- static DXGI_FORMAT calcFormat(UsageType usage, DXGI_FORMAT format);
- /// Calculate appropriate format for creating a buffer for usage and flags
- static DXGI_FORMAT calcResourceFormat(UsageType usage, Int usageFlags, DXGI_FORMAT format);
- /// True if the type is 'typeless'
- static bool isTypeless(DXGI_FORMAT format);
-
- /// Returns number of bits used for color channel for format (for channels with multiple sizes, returns smallest ie RGB565 -> 5)
- static Int getNumColorChannelBits(DXGI_FORMAT fmt);
-
- /// Append text in in, into wide char array
- static void appendWideChars(const char* in, Slang::List<wchar_t>& out);
-};
-
-} // renderer_test
diff --git a/tools/render-test/descriptor-heap-d3d12.cpp b/tools/render-test/descriptor-heap-d3d12.cpp
deleted file mode 100644
index 5bd238528..000000000
--- a/tools/render-test/descriptor-heap-d3d12.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-
-#include "descriptor-heap-d3d12.h"
-
-namespace renderer_test {
-using namespace Slang;
-
-D3D12DescriptorHeap::D3D12DescriptorHeap():
- m_totalSize(0),
- m_currentIndex(0),
- m_descriptorSize(0)
-{
-}
-
-Result D3D12DescriptorHeap::init(ID3D12Device* device, int size, D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12_DESCRIPTOR_HEAP_FLAGS flags)
-{
- D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
- srvHeapDesc.NumDescriptors = size;
- srvHeapDesc.Flags = flags;
- srvHeapDesc.Type = type;
- SLANG_RETURN_ON_FAIL(device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(m_heap.writeRef())));
-
- m_descriptorSize = device->GetDescriptorHandleIncrementSize(type);
- m_totalSize = size;
-
- return SLANG_OK;
-}
-
-Result D3D12DescriptorHeap::init(ID3D12Device* device, const D3D12_CPU_DESCRIPTOR_HANDLE* handles, int numHandles, D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12_DESCRIPTOR_HEAP_FLAGS flags)
-{
- SLANG_RETURN_ON_FAIL(init(device, numHandles, type, flags));
- D3D12_CPU_DESCRIPTOR_HANDLE dst = m_heap->GetCPUDescriptorHandleForHeapStart();
-
- // Copy them all
- for (int i = 0; i < numHandles; i++, dst.ptr += m_descriptorSize)
- {
- D3D12_CPU_DESCRIPTOR_HANDLE src = handles[i];
- if (src.ptr != 0)
- {
- device->CopyDescriptorsSimple(1, dst, src, type);
- }
- }
-
- return SLANG_OK;
-}
-
-} // namespace renderer_test
-
diff --git a/tools/render-test/descriptor-heap-d3d12.h b/tools/render-test/descriptor-heap-d3d12.h
deleted file mode 100644
index 1d0302d2c..000000000
--- a/tools/render-test/descriptor-heap-d3d12.h
+++ /dev/null
@@ -1,115 +0,0 @@
-#pragma once
-
-
-#include <dxgi.h>
-#include <d3d12.h>
-
-#include "../../slang-com-ptr.h"
-
-namespace renderer_test {
-
-/*! \brief A simple class to manage an underlying Dx12 Descriptor Heap. Allocations are made linearly in order. It is not possible to free
-individual allocations, but all allocations can be deallocated with 'deallocateAll'. */
-class D3D12DescriptorHeap
-{
- public:
- typedef D3D12DescriptorHeap ThisType;
-
- /// Initialize
- Slang::Result init(ID3D12Device* device, int size, D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12_DESCRIPTOR_HEAP_FLAGS flags);
- /// Initialize with an array of handles copying over the representation
- Slang::Result init(ID3D12Device* device, const D3D12_CPU_DESCRIPTOR_HANDLE* handles, int numHandles, D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12_DESCRIPTOR_HEAP_FLAGS flags);
-
- /// Returns the number of slots that have been used
- SLANG_FORCE_INLINE int getUsedSize() const { return m_currentIndex; }
-
- /// Get the total amount of descriptors possible on the heap
- SLANG_FORCE_INLINE int getTotalSize() const { return m_totalSize; }
- /// Allocate a descriptor. Returns the index, or -1 if none left.
- SLANG_FORCE_INLINE int allocate();
- /// Allocate a number of descriptors. Returns the start index (or -1 if not possible)
- SLANG_FORCE_INLINE int allocate(int numDescriptors);
-
- ///
- SLANG_FORCE_INLINE int placeAt(int index);
-
- /// Deallocates all allocations, and starts allocation from the start of the underlying heap again
- SLANG_FORCE_INLINE void deallocateAll() { m_currentIndex = 0; }
-
- /// Get the size of each
- SLANG_FORCE_INLINE int getDescriptorSize() const { return m_descriptorSize; }
-
- /// Get the GPU heap start
- SLANG_FORCE_INLINE D3D12_GPU_DESCRIPTOR_HANDLE getGpuStart() const { return m_heap->GetGPUDescriptorHandleForHeapStart(); }
- /// Get the CPU heap start
- SLANG_FORCE_INLINE D3D12_CPU_DESCRIPTOR_HANDLE getCpuStart() const { return m_heap->GetCPUDescriptorHandleForHeapStart(); }
-
- /// Get the GPU handle at the specified index
- SLANG_FORCE_INLINE D3D12_GPU_DESCRIPTOR_HANDLE getGpuHandle(int index) const;
- /// Get the CPU handle at the specified index
- SLANG_FORCE_INLINE D3D12_CPU_DESCRIPTOR_HANDLE getCpuHandle(int index) const;
-
- /// Get the underlying heap
- SLANG_FORCE_INLINE ID3D12DescriptorHeap* getHeap() const { return m_heap; }
-
- /// Ctor
- D3D12DescriptorHeap();
-
-protected:
- Slang::ComPtr<ID3D12DescriptorHeap> m_heap; ///< The underlying heap being allocated from
- int m_totalSize; ///< Total amount of allocations available on the heap
- int m_currentIndex; ///< The current descriptor
- int m_descriptorSize; ///< The size of each descriptor
-};
-
-// ---------------------------------------------------------------------------
-int D3D12DescriptorHeap::allocate()
-{
- assert(m_currentIndex < m_totalSize);
- if (m_currentIndex < m_totalSize)
- {
- return m_currentIndex++;
- }
- return -1;
-}
-// ---------------------------------------------------------------------------
-int D3D12DescriptorHeap::allocate(int numDescriptors)
-{
- assert(m_currentIndex + numDescriptors <= m_totalSize);
- if (m_currentIndex + numDescriptors <= m_totalSize)
- {
- const int index = m_currentIndex;
- m_currentIndex += numDescriptors;
- return index;
- }
- return -1;
-}
-// ---------------------------------------------------------------------------
-SLANG_FORCE_INLINE int D3D12DescriptorHeap::placeAt(int index)
-{
- assert(index >= 0 && index < m_totalSize);
- m_currentIndex = index + 1;
- return index;
-}
-
-// ---------------------------------------------------------------------------
-SLANG_FORCE_INLINE D3D12_CPU_DESCRIPTOR_HANDLE D3D12DescriptorHeap::getCpuHandle(int index) const
-{
- assert(index >= 0 && index < m_totalSize);
- D3D12_CPU_DESCRIPTOR_HANDLE start = m_heap->GetCPUDescriptorHandleForHeapStart();
- D3D12_CPU_DESCRIPTOR_HANDLE dst;
- dst.ptr = start.ptr + m_descriptorSize * index;
- return dst;
-}
-// ---------------------------------------------------------------------------
-SLANG_FORCE_INLINE D3D12_GPU_DESCRIPTOR_HANDLE D3D12DescriptorHeap::getGpuHandle(int index) const
-{
- assert(index >= 0 && index < m_totalSize);
- D3D12_GPU_DESCRIPTOR_HANDLE start = m_heap->GetGPUDescriptorHandleForHeapStart();
- D3D12_GPU_DESCRIPTOR_HANDLE dst;
- dst.ptr = start.ptr + m_descriptorSize * index;
- return dst;
-}
-
-} // namespace renderer_test
-
diff --git a/tools/render-test/options.h b/tools/render-test/options.h
index a14acec15..82c018f66 100644
--- a/tools/render-test/options.h
+++ b/tools/render-test/options.h
@@ -9,6 +9,8 @@
namespace renderer_test {
+using namespace slang_graphics;
+
struct Options
{
enum
@@ -25,7 +27,7 @@ struct Options
// Raw HLSL or GLSL input, bypassing Slang
Native,
};
-
+
enum class ShaderProgramType
{
diff --git a/tools/render-test/png-serialize-util.h b/tools/render-test/png-serialize-util.h
index fe3b4f873..dad17ae74 100644
--- a/tools/render-test/png-serialize-util.h
+++ b/tools/render-test/png-serialize-util.h
@@ -2,10 +2,12 @@
#pragma once
#include "surface.h"
-
+
namespace renderer_test {
-struct PngSerializeUtil
+using namespace slang_graphics;
+
+struct PngSerializeUtil
{
static Slang::Result write(const char* filename, const Surface& surface);
diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp
deleted file mode 100644
index 109c5aca1..000000000
--- a/tools/render-test/render-d3d11.cpp
+++ /dev/null
@@ -1,1101 +0,0 @@
-// render-d3d11.cpp
-
-#define _CRT_SECURE_NO_WARNINGS
-
-#include "render-d3d11.h"
-
-#include "options.h"
-#include "render.h"
-#include "d3d-util.h"
-
-#include "surface.h"
-
-// In order to use the Slang API, we need to include its header
-
-#include <slang.h>
-
-#include "../../slang-com-ptr.h"
-
-// We will be rendering with Direct3D 11, so we need to include
-// the Windows and D3D11 headers
-
-#define WIN32_LEAN_AND_MEAN
-#define NOMINMAX
-#include <Windows.h>
-#undef WIN32_LEAN_AND_MEAN
-#undef NOMINMAX
-
-#include <d3d11_2.h>
-#include <d3dcompiler.h>
-
-// We will use the C standard library just for printing error messages.
-#include <stdio.h>
-
-#ifdef _MSC_VER
-#include <stddef.h>
-#if (_MSC_VER < 1900)
-#define snprintf sprintf_s
-#endif
-#endif
-//
-using namespace Slang;
-
-namespace renderer_test {
-
-class D3D11Renderer : public Renderer
-{
-public:
- // 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& surfaceOut) override;
- virtual InputLayout* createInputLayout( const InputElementDesc* inputElements, UInt inputElementCount) override;
- virtual BindingState* createBindingState(const BindingState::Desc& desc) 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::DirectX11; }
-
- protected:
-
- struct BindingDetail
- {
- ComPtr<ID3D11ShaderResourceView> m_srv;
- ComPtr<ID3D11UnorderedAccessView> m_uav;
- ComPtr<ID3D11SamplerState> m_samplerState;
- };
-
- class BindingStateImpl: public BindingState
- {
- public:
- typedef BindingState Parent;
-
- /// Ctor
- BindingStateImpl(const Desc& desc):
- Parent(desc)
- {}
-
- List<BindingDetail> m_bindingDetails;
- };
-
- class ShaderProgramImpl: public ShaderProgram
- {
- public:
- ComPtr<ID3D11VertexShader> m_vertexShader;
- ComPtr<ID3D11PixelShader> m_pixelShader;
- ComPtr<ID3D11ComputeShader> m_computeShader;
- };
-
- class BufferResourceImpl: public BufferResource
- {
- public:
- typedef BufferResource Parent;
-
- BufferResourceImpl(const Desc& desc, Usage initialUsage):
- Parent(desc),
- m_initialUsage(initialUsage)
- {
- }
-
- MapFlavor m_mapFlavor;
- Usage m_initialUsage;
- ComPtr<ID3D11Buffer> m_buffer;
- ComPtr<ID3D11Buffer> m_staging;
- };
- class TextureResourceImpl : public TextureResource
- {
- public:
- typedef TextureResource Parent;
-
- TextureResourceImpl(const Desc& desc, Usage initialUsage) :
- Parent(desc),
- m_initialUsage(initialUsage)
- {
- }
- Usage m_initialUsage;
- ComPtr<ID3D11Resource> m_resource;
- };
-
- class InputLayoutImpl: public InputLayout
- {
- public:
- ComPtr<ID3D11InputLayout> m_layout;
- };
-
- /// Capture a texture to a file
- static HRESULT captureTextureToSurface(ID3D11Device* device, ID3D11DeviceContext* context, ID3D11Texture2D* texture, Surface& surfaceOut);
-
- void _applyBindingState(bool isCompute);
-
- ComPtr<IDXGISwapChain> m_swapChain;
- ComPtr<ID3D11Device> m_device;
- ComPtr<ID3D11DeviceContext> m_immediateContext;
- ComPtr<ID3D11Texture2D> m_backBufferTexture;
-
- List<ComPtr<ID3D11RenderTargetView> > m_renderTargetViews;
- List<ComPtr<ID3D11Texture2D> > m_renderTargetTextures;
-
- RefPtr<BindingStateImpl> m_currentBindings;
-
- Desc m_desc;
-
- float m_clearColor[4] = { 0, 0, 0, 0 };
-};
-
-Renderer* createD3D11Renderer()
-{
- return new D3D11Renderer();
-}
-
-/* static */HRESULT D3D11Renderer::captureTextureToSurface(ID3D11Device* device, ID3D11DeviceContext* context, ID3D11Texture2D* texture, Surface& surfaceOut)
-{
- if (!context) return E_INVALIDARG;
- if (!texture) return E_INVALIDARG;
-
- D3D11_TEXTURE2D_DESC textureDesc;
- texture->GetDesc(&textureDesc);
-
- // Don't bother supporting MSAA for right now
- if (textureDesc.SampleDesc.Count > 1)
- {
- fprintf(stderr, "ERROR: cannot capture multi-sample texture\n");
- return E_INVALIDARG;
- }
-
- HRESULT hr = S_OK;
- ComPtr<ID3D11Texture2D> stagingTexture;
-
- if (textureDesc.Usage == D3D11_USAGE_STAGING && (textureDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ))
- {
- stagingTexture = texture;
- }
- else
- {
- // Modify the descriptor to give us a staging texture
- textureDesc.BindFlags = 0;
- textureDesc.MiscFlags &= ~D3D11_RESOURCE_MISC_TEXTURECUBE;
- textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- textureDesc.Usage = D3D11_USAGE_STAGING;
-
- hr = device->CreateTexture2D(&textureDesc, 0, stagingTexture.writeRef());
- if (FAILED(hr))
- {
- fprintf(stderr, "ERROR: failed to create staging texture\n");
- return hr;
- }
-
- context->CopyResource(stagingTexture, texture);
- }
-
- // Now just read back texels from the staging textures
- {
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- SLANG_RETURN_ON_FAIL(context->Map(stagingTexture, 0, D3D11_MAP_READ, 0, &mappedResource));
-
- Result res = surfaceOut.set(textureDesc.Width, textureDesc.Height, Format::RGBA_Unorm_UInt8, mappedResource.RowPitch, mappedResource.pData, SurfaceAllocator::getMallocAllocator());
-
- // Make sure to unmap
- context->Unmap(stagingTexture, 0);
- return res;
- }
-}
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
-
-SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
-{
- auto windowHandle = (HWND)inWindowHandle;
- m_desc = desc;
-
- // Rather than statically link against D3D, we load it dynamically.
- HMODULE d3dModule = LoadLibraryA("d3d11.dll");
- if (!d3dModule)
- {
- fprintf(stderr, "error: failed load 'd3d11.dll'\n");
- return SLANG_FAIL;
- }
-
- PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN D3D11CreateDeviceAndSwapChain_ =
- (PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN)GetProcAddress(d3dModule, "D3D11CreateDeviceAndSwapChain");
- if (!D3D11CreateDeviceAndSwapChain_)
- {
- fprintf(stderr,
- "error: failed load symbol 'D3D11CreateDeviceAndSwapChain'\n");
- return SLANG_FAIL;
- }
-
- // We create our device in debug mode, just so that we can check that the
- // example doesn't trigger warnings.
- UINT deviceFlags = 0;
- deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
-
- // Our swap chain uses RGBA8 with sRGB, with double buffering.
- DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
- swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-
- // Note(tfoley): Disabling sRGB for DX back buffer for now, so that we
- // can get consistent output with OpenGL, where setting up sRGB will
- // probably be more involved.
- // swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
- swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
-
- swapChainDesc.SampleDesc.Count = 1;
- swapChainDesc.SampleDesc.Quality = 0;
- swapChainDesc.BufferCount = 2;
- swapChainDesc.OutputWindow = windowHandle;
- swapChainDesc.Windowed = TRUE;
- swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
- swapChainDesc.Flags = 0;
-
- // We will ask for the highest feature level that can be supported.
- const D3D_FEATURE_LEVEL featureLevels[] = {
- D3D_FEATURE_LEVEL_11_1,
- D3D_FEATURE_LEVEL_11_0,
- D3D_FEATURE_LEVEL_10_1,
- D3D_FEATURE_LEVEL_10_0,
- D3D_FEATURE_LEVEL_9_3,
- D3D_FEATURE_LEVEL_9_2,
- D3D_FEATURE_LEVEL_9_1,
- };
- D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_9_1;
- const int totalNumFeatureLevels = SLANG_COUNT_OF(featureLevels);
-
- // On a machine that does not have an up-to-date version of D3D installed,
- // the `D3D11CreateDeviceAndSwapChain` call will fail with `E_INVALIDARG`
- // if you ask for featuer level 11_1. The workaround is to call
- // `D3D11CreateDeviceAndSwapChain` up to twice: the first time with 11_1
- // at the start of the list of requested feature levels, and the second
- // time without it.
-
- for (int ii = 0; ii < 2; ++ii)
- {
- const HRESULT hr = D3D11CreateDeviceAndSwapChain_(
- nullptr, // adapter (use default)
- D3D_DRIVER_TYPE_REFERENCE,
- //D3D_DRIVER_TYPE_HARDWARE,
- nullptr, // software
- deviceFlags,
- &featureLevels[ii],
- totalNumFeatureLevels - ii,
- D3D11_SDK_VERSION,
- &swapChainDesc,
- m_swapChain.writeRef(),
- m_device.writeRef(),
- &featureLevel,
- m_immediateContext.writeRef());
-
- // Failures with `E_INVALIDARG` might be due to feature level 11_1
- // not being supported.
- if (hr == E_INVALIDARG)
- {
- continue;
- }
-
- // Other failures are real, though.
- SLANG_RETURN_ON_FAIL(hr);
- // We must have a swap chain
- break;
- }
-
- // After we've created the swap chain, we can request a pointer to the
- // back buffer as a D3D11 texture, and create a render-target view from it.
-
- static const IID kIID_ID3D11Texture2D = {
- 0x6f15aaf2, 0xd208, 0x4e89, 0x9a, 0xb4, 0x48,
- 0x95, 0x35, 0xd3, 0x4f, 0x9c };
-
- SLANG_RETURN_ON_FAIL(m_swapChain->GetBuffer(0, kIID_ID3D11Texture2D, (void**)m_backBufferTexture.writeRef()));
-
- for (int i = 0; i < 8; i++)
- {
- ComPtr<ID3D11Texture2D> texture;
- D3D11_TEXTURE2D_DESC textureDesc;
- m_backBufferTexture->GetDesc(&textureDesc);
- SLANG_RETURN_ON_FAIL(m_device->CreateTexture2D(&textureDesc, nullptr, texture.writeRef()));
-
- ComPtr<ID3D11RenderTargetView> rtv;
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- rtvDesc.Texture2D.MipSlice = 0;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
- SLANG_RETURN_ON_FAIL(m_device->CreateRenderTargetView(texture, &rtvDesc, rtv.writeRef()));
-
- m_renderTargetViews.Add(rtv);
- m_renderTargetTextures.Add(texture);
- }
-
- m_immediateContext->OMSetRenderTargets((UINT)m_renderTargetViews.Count(), m_renderTargetViews.Buffer()->readRef(), nullptr);
-
- // Similarly, we are going to set up a viewport once, and then never
- // switch, since this is a simple test app.
- D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
- viewport.Width = (float)desc.width;
- viewport.Height = (float)desc.height;
- viewport.MaxDepth = 1; // TODO(tfoley): use reversed depth
- viewport.MinDepth = 0;
- m_immediateContext->RSSetViewports(1, &viewport);
-
- return SLANG_OK;
-}
-
-void D3D11Renderer::setClearColor(const float color[4])
-{
- memcpy(m_clearColor, color, sizeof(m_clearColor));
-}
-
-void D3D11Renderer::clearFrame()
-{
- for (auto i = 0u; i < m_renderTargetViews.Count(); i++)
- {
- m_immediateContext->ClearRenderTargetView(m_renderTargetViews[i], m_clearColor);
- }
-}
-
-void D3D11Renderer::presentFrame()
-{
- m_immediateContext->CopyResource(m_backBufferTexture, m_renderTargetTextures[0]);
- m_swapChain->Present(0, 0);
-}
-
-SlangResult D3D11Renderer::captureScreenSurface(Surface& surfaceOut)
-{
- return captureTextureToSurface(m_device, m_immediateContext, m_renderTargetTextures[0], surfaceOut);
-}
-
-static D3D11_BIND_FLAG _calcResourceFlag(Resource::BindFlag::Enum bindFlag)
-{
- typedef Resource::BindFlag BindFlag;
- switch (bindFlag)
- {
- case BindFlag::VertexBuffer: return D3D11_BIND_VERTEX_BUFFER;
- case BindFlag::IndexBuffer: return D3D11_BIND_INDEX_BUFFER;
- case BindFlag::ConstantBuffer: return D3D11_BIND_CONSTANT_BUFFER;
- case BindFlag::StreamOutput: return D3D11_BIND_STREAM_OUTPUT;
- case BindFlag::RenderTarget: return D3D11_BIND_RENDER_TARGET;
- case BindFlag::DepthStencil: return D3D11_BIND_DEPTH_STENCIL;
- case BindFlag::UnorderedAccess: return D3D11_BIND_UNORDERED_ACCESS;
- case BindFlag::PixelShaderResource: return D3D11_BIND_SHADER_RESOURCE;
- case BindFlag::NonPixelShaderResource: return D3D11_BIND_SHADER_RESOURCE;
- default: return D3D11_BIND_FLAG(0);
- }
-}
-
-static int _calcResourceBindFlags(int bindFlags)
-{
- int dstFlags = 0;
- while (bindFlags)
- {
- int lsb = bindFlags & -bindFlags;
-
- dstFlags |= _calcResourceFlag(Resource::BindFlag::Enum(lsb));
- bindFlags &= ~lsb;
- }
- return dstFlags;
-}
-
-static int _calcResourceAccessFlags(int accessFlags)
-{
- switch (accessFlags)
- {
- case 0: return 0;
- case Resource::AccessFlag::Read: return D3D11_CPU_ACCESS_READ;
- case Resource::AccessFlag::Write: return D3D11_CPU_ACCESS_WRITE;
- case Resource::AccessFlag::Read |
- Resource::AccessFlag::Write: return D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
- default: assert(!"Invalid flags"); return 0;
- }
-}
-
-TextureResource* D3D11Renderer::createTextureResource(Resource::Usage initialUsage, const TextureResource::Desc& descIn, const TextureResource::Data* initData)
-{
- TextureResource::Desc srcDesc(descIn);
- srcDesc.setDefaults(initialUsage);
-
- const int effectiveArraySize = srcDesc.calcEffectiveArraySize();
-
- assert(initData);
- assert(initData->numSubResources == srcDesc.numMipLevels * effectiveArraySize * srcDesc.size.depth);
-
- const DXGI_FORMAT format = D3DUtil::getMapFormat(srcDesc.format);
- if (format == DXGI_FORMAT_UNKNOWN)
- {
- return nullptr;
- }
-
- const int bindFlags = _calcResourceBindFlags(srcDesc.bindFlags);
-
- // Set up the initialize data
- List<D3D11_SUBRESOURCE_DATA> subRes;
- subRes.SetSize(srcDesc.numMipLevels * effectiveArraySize);
- {
- int subResourceIndex = 0;
- for (int i = 0; i < effectiveArraySize; i++)
- {
- for (int j = 0; j < srcDesc.numMipLevels; j++)
- {
- const int mipHeight = TextureResource::calcMipSize(srcDesc.size.height, j);
-
- D3D11_SUBRESOURCE_DATA& data = subRes[subResourceIndex];
-
- data.pSysMem = initData->subResources[subResourceIndex];
-
- data.SysMemPitch = UINT(initData->mipRowStrides[j]);
- data.SysMemSlicePitch = UINT(initData->mipRowStrides[j] * mipHeight);
-
- subResourceIndex++;
- }
- }
- }
-
- const int accessFlags = _calcResourceAccessFlags(srcDesc.cpuAccessFlags);
-
- RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(srcDesc, initialUsage));
-
- switch (srcDesc.type)
- {
- case Resource::Type::Texture1D:
- {
- D3D11_TEXTURE1D_DESC desc = { 0 };
- desc.BindFlags = bindFlags;
- desc.CPUAccessFlags = accessFlags;
- desc.Format = format;
- desc.MiscFlags = 0;
- desc.MipLevels = srcDesc.numMipLevels;
- desc.ArraySize = effectiveArraySize;
- desc.Width = srcDesc.size.width;
- desc.Usage = D3D11_USAGE_DEFAULT;
-
- ComPtr<ID3D11Texture1D> texture1D;
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateTexture1D(&desc, subRes.Buffer(), texture1D.writeRef()));
-
- texture->m_resource = texture1D;
- break;
- }
- case Resource::Type::TextureCube:
- case Resource::Type::Texture2D:
- {
- D3D11_TEXTURE2D_DESC desc = { 0 };
- desc.BindFlags = bindFlags;
- desc.CPUAccessFlags = accessFlags;
- desc.Format = format;
- desc.MiscFlags = 0;
- desc.MipLevels = srcDesc.numMipLevels;
- desc.ArraySize = effectiveArraySize;
-
- desc.Width = srcDesc.size.width;
- desc.Height = srcDesc.size.height;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.SampleDesc.Count = srcDesc.sampleDesc.numSamples;
- desc.SampleDesc.Quality = srcDesc.sampleDesc.quality;
-
- if (srcDesc.type == Resource::Type::TextureCube)
- {
- desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
- }
-
- ComPtr<ID3D11Texture2D> texture2D;
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateTexture2D(&desc, subRes.Buffer(), texture2D.writeRef()));
-
- texture->m_resource = texture2D;
- break;
- }
- case Resource::Type::Texture3D:
- {
- D3D11_TEXTURE3D_DESC desc = { 0 };
- desc.BindFlags = bindFlags;
- desc.CPUAccessFlags = accessFlags;
- desc.Format = format;
- desc.MiscFlags = 0;
- desc.MipLevels = srcDesc.numMipLevels;
- desc.Width = srcDesc.size.width;
- desc.Height = srcDesc.size.height;
- desc.Depth = srcDesc.size.depth;
- desc.Usage = D3D11_USAGE_DEFAULT;
-
- ComPtr<ID3D11Texture3D> texture3D;
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateTexture3D(&desc, subRes.Buffer(), texture3D.writeRef()));
-
- texture->m_resource = texture3D;
- break;
- }
- default: return nullptr;
- }
-
- return texture.detach();
-}
-
-BufferResource* D3D11Renderer::createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData)
-{
- BufferResource::Desc srcDesc(descIn);
- srcDesc.setDefaults(initialUsage);
-
- // Make aligned to 256 bytes... not sure why, but if you remove this the tests do fail.
- const size_t alignedSizeInBytes = D3DUtil::calcAligned(srcDesc.sizeInBytes, 256);
-
- // Hack to make the initialization never read from out of bounds memory, by copying into a buffer
- List<uint8_t> initDataBuffer;
- if (initData && alignedSizeInBytes > srcDesc.sizeInBytes)
- {
- initDataBuffer.SetSize(alignedSizeInBytes);
- ::memcpy(initDataBuffer.Buffer(), initData, srcDesc.sizeInBytes);
- initData = initDataBuffer.Buffer();
- }
-
- D3D11_BUFFER_DESC bufferDesc = { 0 };
- bufferDesc.ByteWidth = UINT(alignedSizeInBytes);
- bufferDesc.BindFlags = _calcResourceBindFlags(srcDesc.bindFlags);
- // For read we'll need to do some staging
- bufferDesc.CPUAccessFlags = _calcResourceAccessFlags(descIn.cpuAccessFlags & Resource::AccessFlag::Write);
- bufferDesc.Usage = D3D11_USAGE_DEFAULT;
-
- // If written by CPU, make it dynamic
- if (descIn.cpuAccessFlags & Resource::AccessFlag::Write)
- {
- bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
- }
-
- switch (initialUsage)
- {
- case Resource::Usage::ConstantBuffer:
- {
- // We'll just assume ConstantBuffers are dynamic for now
- bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
- break;
- }
- default: break;
- }
-
- if (bufferDesc.BindFlags & (D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE))
- {
- //desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
- if (srcDesc.elementSize != 0)
- {
- bufferDesc.StructureByteStride = srcDesc.elementSize;
- bufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
- }
- else
- {
- bufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
- }
- }
-
- D3D11_SUBRESOURCE_DATA subResourceData = { 0 };
- subResourceData.pSysMem = initData;
-
- RefPtr<BufferResourceImpl> buffer(new BufferResourceImpl(srcDesc, initialUsage));
-
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateBuffer(&bufferDesc, initData ? &subResourceData : nullptr, buffer->m_buffer.writeRef()));
-
- if (srcDesc.cpuAccessFlags & Resource::AccessFlag::Read)
- {
- D3D11_BUFFER_DESC bufDesc = {};
- bufDesc.BindFlags = 0;
- bufDesc.ByteWidth = (UINT)alignedSizeInBytes;
- bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- bufDesc.Usage = D3D11_USAGE_STAGING;
-
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateBuffer(&bufDesc, nullptr, buffer->m_staging.writeRef()));
- }
-
- return buffer.detach();
-}
-
-InputLayout* D3D11Renderer::createInputLayout(const InputElementDesc* inputElementsIn, UInt inputElementCount)
-{
- D3D11_INPUT_ELEMENT_DESC inputElements[16] = {};
-
- char hlslBuffer[1024];
- char* hlslCursor = &hlslBuffer[0];
-
- hlslCursor += sprintf(hlslCursor, "float4 main(\n");
-
- for (UInt ii = 0; ii < inputElementCount; ++ii)
- {
- inputElements[ii].SemanticName = inputElementsIn[ii].semanticName;
- inputElements[ii].SemanticIndex = (UINT)inputElementsIn[ii].semanticIndex;
- inputElements[ii].Format = D3DUtil::getMapFormat(inputElementsIn[ii].format);
- inputElements[ii].InputSlot = 0;
- inputElements[ii].AlignedByteOffset = (UINT)inputElementsIn[ii].offset;
- inputElements[ii].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
- inputElements[ii].InstanceDataStepRate = 0;
-
- if (ii != 0)
- {
- hlslCursor += sprintf(hlslCursor, ",\n");
- }
-
- char const* typeName = "Unknown";
- switch (inputElementsIn[ii].format)
- {
- case Format::RGBA_Float32:
- typeName = "float4";
- break;
- case Format::RGB_Float32:
- typeName = "float3";
- break;
- case Format::RG_Float32:
- typeName = "float2";
- break;
- case Format::R_Float32:
- typeName = "float";
- break;
- default:
- return nullptr;
- }
-
- hlslCursor += sprintf(hlslCursor, "%s a%d : %s%d",
- typeName,
- (int)ii,
- inputElementsIn[ii].semanticName,
- (int)inputElementsIn[ii].semanticIndex);
- }
-
- hlslCursor += sprintf(hlslCursor, "\n) : SV_Position { return 0; }");
-
- ComPtr<ID3DBlob> vertexShaderBlob;
- SLANG_RETURN_NULL_ON_FAIL(D3DUtil::compileHLSLShader("inputLayout", hlslBuffer, "main", "vs_5_0", vertexShaderBlob));
-
- ComPtr<ID3D11InputLayout> inputLayout;
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateInputLayout(&inputElements[0], (UINT)inputElementCount, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(),
- inputLayout.writeRef()));
-
- InputLayoutImpl* impl = new InputLayoutImpl;
- impl->m_layout.swap(inputLayout);
-
- return impl;
-}
-
-void* D3D11Renderer::map(BufferResource* bufferIn, MapFlavor flavor)
-{
- BufferResourceImpl* bufferResource = static_cast<BufferResourceImpl*>(bufferIn);
-
- D3D11_MAP mapType;
- ID3D11Buffer* buffer = bufferResource->m_buffer;
-
- switch (flavor)
- {
- case MapFlavor::WriteDiscard:
- mapType = D3D11_MAP_WRITE_DISCARD;
- break;
- case MapFlavor::HostWrite:
- mapType = D3D11_MAP_WRITE;
- break;
- case MapFlavor::HostRead:
- mapType = D3D11_MAP_READ;
-
- buffer = bufferResource->m_staging;
- if (!buffer)
- {
- return nullptr;
- }
-
- // Okay copy the data over
- m_immediateContext->CopyResource(buffer, bufferResource->m_buffer);
-
- break;
- default:
- return nullptr;
- }
-
- // We update our constant buffer per-frame, just for the purposes
- // of the example, but we don't actually load different data
- // per-frame (we always use an identity projection).
- D3D11_MAPPED_SUBRESOURCE mappedSub;
- SLANG_RETURN_NULL_ON_FAIL(m_immediateContext->Map(buffer, 0, mapType, 0, &mappedSub));
-
- bufferResource->m_mapFlavor = flavor;
-
- return mappedSub.pData;
-}
-
-void D3D11Renderer::unmap(BufferResource* bufferIn)
-{
- BufferResourceImpl* bufferResource = static_cast<BufferResourceImpl*>(bufferIn);
- ID3D11Buffer* buffer = (bufferResource->m_mapFlavor == MapFlavor::HostRead) ? bufferResource->m_staging : bufferResource->m_buffer;
- m_immediateContext->Unmap(buffer, 0);
-}
-
-void D3D11Renderer::setInputLayout(InputLayout* inputLayoutIn)
-{
- auto inputLayout = static_cast<InputLayoutImpl*>(inputLayoutIn);
- m_immediateContext->IASetInputLayout(inputLayout->m_layout);
-}
-
-void D3D11Renderer::setPrimitiveTopology(PrimitiveTopology topology)
-{
- m_immediateContext->IASetPrimitiveTopology(D3DUtil::getPrimitiveTopology(topology));
-}
-
-void D3D11Renderer::setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffersIn, const UInt* stridesIn, const UInt* offsetsIn)
-{
- static const int kMaxVertexBuffers = 16;
- assert(slotCount <= kMaxVertexBuffers);
-
- UINT vertexStrides[kMaxVertexBuffers];
- UINT vertexOffsets[kMaxVertexBuffers];
- ID3D11Buffer* dxBuffers[kMaxVertexBuffers];
-
- auto buffers = (BufferResourceImpl*const*)buffersIn;
-
- for (UInt ii = 0; ii < slotCount; ++ii)
- {
- vertexStrides[ii] = (UINT)stridesIn[ii];
- vertexOffsets[ii] = (UINT)offsetsIn[ii];
- dxBuffers[ii] = buffers[ii]->m_buffer;
- }
-
- m_immediateContext->IASetVertexBuffers((UINT)startSlot, (UINT)slotCount, dxBuffers, &vertexStrides[0], &vertexOffsets[0]);
-}
-
-void D3D11Renderer::setShaderProgram(ShaderProgram* programIn)
-{
- auto program = (ShaderProgramImpl*)programIn;
- m_immediateContext->CSSetShader(program->m_computeShader, nullptr, 0);
- m_immediateContext->VSSetShader(program->m_vertexShader, nullptr, 0);
- m_immediateContext->PSSetShader(program->m_pixelShader, nullptr, 0);
-}
-
-void D3D11Renderer::draw(UInt vertexCount, UInt startVertex)
-{
- _applyBindingState(false);
- m_immediateContext->Draw((UINT)vertexCount, (UINT)startVertex);
-}
-
-ShaderProgram* D3D11Renderer::createProgram(const ShaderProgram::Desc& desc)
-{
- if (desc.pipelineType == PipelineType::Compute)
- {
- auto computeKernel = desc.findKernel(StageType::Compute);
-
- ComPtr<ID3D11ComputeShader> computeShader;
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateComputeShader(computeKernel->codeBegin, computeKernel->getCodeSize(), nullptr, computeShader.writeRef()));
-
- ShaderProgramImpl* shaderProgram = new ShaderProgramImpl();
- shaderProgram->m_computeShader.swap(computeShader);
- return shaderProgram;
- }
- else
- {
- auto vertexKernel = desc.findKernel(StageType::Vertex);
- auto fragmentKernel = desc.findKernel(StageType::Fragment);
-
- ComPtr<ID3D11VertexShader> vertexShader;
- ComPtr<ID3D11PixelShader> pixelShader;
-
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateVertexShader(vertexKernel->codeBegin, vertexKernel->getCodeSize(), nullptr, vertexShader.writeRef()));
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreatePixelShader(fragmentKernel->codeBegin, fragmentKernel->getCodeSize(), nullptr, pixelShader.writeRef()));
-
- ShaderProgramImpl* shaderProgram = new ShaderProgramImpl();
- shaderProgram->m_vertexShader.swap(vertexShader);
- shaderProgram->m_pixelShader.swap(pixelShader);
- return shaderProgram;
- }
-}
-
-void D3D11Renderer::dispatchCompute(int x, int y, int z)
-{
- _applyBindingState(true);
- m_immediateContext->Dispatch(x, y, z);
-}
-
-BindingState* D3D11Renderer::createBindingState(const BindingState::Desc& bindingStateDesc)
-{
- RefPtr<BindingStateImpl> bindingState(new BindingStateImpl(bindingStateDesc));
-
- 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];
-
- assert(srcBinding.registerRange.isSingle());
-
- switch (srcBinding.bindingType)
- {
- case BindingType::Buffer:
- {
- assert(srcBinding.resource && srcBinding.resource->isBuffer());
-
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(srcBinding.resource.Ptr());
- const BufferResource::Desc& bufferDesc = buffer->getDesc();
-
- const int elemSize = bufferDesc.elementSize <= 0 ? 1 : bufferDesc.elementSize;
-
- if (bufferDesc.bindFlags & Resource::BindFlag::UnorderedAccess)
- {
- D3D11_UNORDERED_ACCESS_VIEW_DESC viewDesc;
- memset(&viewDesc, 0, sizeof(viewDesc));
- viewDesc.Buffer.FirstElement = 0;
- viewDesc.Buffer.NumElements = (UINT)(bufferDesc.sizeInBytes / elemSize);
- viewDesc.Buffer.Flags = 0;
- viewDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
- viewDesc.Format = D3DUtil::getMapFormat(bufferDesc.format);
-
- if (bufferDesc.elementSize == 0 && bufferDesc.format == Format::Unknown)
- {
- viewDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_RAW;
- viewDesc.Format = DXGI_FORMAT_R32_TYPELESS;
- }
-
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateUnorderedAccessView(buffer->m_buffer, &viewDesc, dstDetail.m_uav.writeRef()));
- }
- if (bufferDesc.bindFlags & (Resource::BindFlag::NonPixelShaderResource | Resource::BindFlag::PixelShaderResource))
- {
- D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
- memset(&viewDesc, 0, sizeof(viewDesc));
- viewDesc.Buffer.FirstElement = 0;
- viewDesc.Buffer.ElementWidth = elemSize;
- viewDesc.Buffer.NumElements = (UINT)(bufferDesc.sizeInBytes / elemSize);
- viewDesc.Buffer.ElementOffset = 0;
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
- viewDesc.Format = DXGI_FORMAT_UNKNOWN;
-
- if (bufferDesc.elementSize == 0)
- {
- viewDesc.Format = DXGI_FORMAT_R32_FLOAT;
- }
-
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateShaderResourceView(buffer->m_buffer, &viewDesc, dstDetail.m_srv.writeRef()));
- }
- break;
- }
- case BindingType::Texture:
- case BindingType::CombinedTextureSampler:
- {
- assert(srcBinding.resource && srcBinding.resource->isTexture());
-
- TextureResourceImpl* texture = static_cast<TextureResourceImpl*>(srcBinding.resource.Ptr());
-
- const TextureResource::Desc& textureDesc = texture->getDesc();
-
- D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
- viewDesc.Format = D3DUtil::getMapFormat(textureDesc.format);
-
- switch (texture->getType())
- {
- case Resource::Type::Texture1D:
- {
- if (textureDesc.arraySize <= 0)
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
- viewDesc.Texture1D.MipLevels = textureDesc.numMipLevels;
- viewDesc.Texture1D.MostDetailedMip = 0;
- }
- else
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
- viewDesc.Texture1DArray.ArraySize = textureDesc.arraySize;
- viewDesc.Texture1DArray.FirstArraySlice = 0;
- viewDesc.Texture1DArray.MipLevels = textureDesc.numMipLevels;
- viewDesc.Texture1DArray.MostDetailedMip = 0;
- }
- break;
- }
- case Resource::Type::Texture2D:
- {
- if (textureDesc.arraySize <= 0)
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- viewDesc.Texture2D.MipLevels = textureDesc.numMipLevels;
- viewDesc.Texture2D.MostDetailedMip = 0;
- }
- else
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
- viewDesc.Texture2DArray.ArraySize = textureDesc.arraySize;
- viewDesc.Texture2DArray.FirstArraySlice = 0;
- viewDesc.Texture2DArray.MipLevels = textureDesc.numMipLevels;
- viewDesc.Texture2DArray.MostDetailedMip = 0;
- }
- break;
- }
- case Resource::Type::TextureCube:
- {
- if (textureDesc.arraySize <= 0)
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
- viewDesc.TextureCube.MipLevels = textureDesc.numMipLevels;
- viewDesc.TextureCube.MostDetailedMip = 0;
- }
- else
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
- viewDesc.TextureCubeArray.MipLevels = textureDesc.numMipLevels;
- viewDesc.TextureCubeArray.MostDetailedMip = 0;
- viewDesc.TextureCubeArray.First2DArrayFace = 0;
- viewDesc.TextureCubeArray.NumCubes = textureDesc.arraySize;
- }
- break;
- }
- case Resource::Type::Texture3D:
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
- viewDesc.Texture3D.MipLevels = textureDesc.numMipLevels; // Old code fixed as one
- viewDesc.Texture3D.MostDetailedMip = 0;
- break;
- }
- default:
- {
- assert(!"Unhandled type");
- return nullptr;
- }
- }
-
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateShaderResourceView(texture->m_resource, &viewDesc, dstDetail.m_srv.writeRef()));
- break;
- }
- case BindingType::Sampler:
- {
- const BindingState::SamplerDesc& samplerDesc = bindingStateDesc.m_samplerDescs[srcBinding.descIndex];
-
- D3D11_SAMPLER_DESC desc = {};
- desc.AddressU = desc.AddressV = desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
-
- if (samplerDesc.isCompareSampler)
- {
- desc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;
- desc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
- desc.MinLOD = desc.MaxLOD = 0.0f;
- }
- else
- {
- desc.Filter = D3D11_FILTER_ANISOTROPIC;
- desc.MaxAnisotropy = 8;
- desc.MinLOD = 0.0f;
- desc.MaxLOD = 100.0f;
- }
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateSamplerState(&desc, dstDetail.m_samplerState.writeRef()));
- break;
- }
- default:
- {
- assert(!"Unhandled type");
- return nullptr;
- }
- }
- }
-
- // Done
- return bindingState.detach();
-}
-
-void D3D11Renderer::_applyBindingState(bool isCompute)
-{
- auto context = m_immediateContext.get();
-
- const auto& details = m_currentBindings->m_bindingDetails;
- const auto& bindings = m_currentBindings->getDesc().m_bindings;
-
- const int numBindings = int(bindings.Count());
-
- for (int i = 0; i < numBindings; ++i)
- {
- const auto& binding = bindings[i];
- const auto& detail = details[i];
-
- const int bindingIndex = binding.registerRange.getSingleIndex();
-
- switch (binding.bindingType)
- {
- case BindingType::Buffer:
- {
- assert(binding.resource && binding.resource->isBuffer());
- if (binding.resource->canBind(Resource::BindFlag::ConstantBuffer))
- {
- ID3D11Buffer* buffer = static_cast<BufferResourceImpl*>(binding.resource.Ptr())->m_buffer;
- if (isCompute)
- context->CSSetConstantBuffers(bindingIndex, 1, &buffer);
- else
- {
- context->VSSetConstantBuffers(bindingIndex, 1, &buffer);
- context->PSSetConstantBuffers(bindingIndex, 1, &buffer);
- }
- }
- else if (detail.m_uav)
- {
- if (isCompute)
- context->CSSetUnorderedAccessViews(bindingIndex, 1, detail.m_uav.readRef(), nullptr);
- else
- context->OMSetRenderTargetsAndUnorderedAccessViews(m_currentBindings->getDesc().m_numRenderTargets,
- m_renderTargetViews.Buffer()->readRef(), nullptr, bindingIndex, 1, detail.m_uav.readRef(), nullptr);
- }
- else
- {
- if (isCompute)
- context->CSSetShaderResources(bindingIndex, 1, detail.m_srv.readRef());
- else
- {
- context->PSSetShaderResources(bindingIndex, 1, detail.m_srv.readRef());
- context->VSSetShaderResources(bindingIndex, 1, detail.m_srv.readRef());
- }
- }
- break;
- }
- case BindingType::Texture:
- {
- if (detail.m_uav)
- {
- if (isCompute)
- context->CSSetUnorderedAccessViews(bindingIndex, 1, detail.m_uav.readRef(), nullptr);
- else
- context->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL,
- nullptr, nullptr, bindingIndex, 1, detail.m_uav.readRef(), nullptr);
- }
- else
- {
- if (isCompute)
- context->CSSetShaderResources(bindingIndex, 1, detail.m_srv.readRef());
- else
- {
- context->PSSetShaderResources(bindingIndex, 1, detail.m_srv.readRef());
- context->VSSetShaderResources(bindingIndex, 1, detail.m_srv.readRef());
- }
- }
- break;
- }
- case BindingType::Sampler:
- {
- if (isCompute)
- context->CSSetSamplers(bindingIndex, 1, detail.m_samplerState.readRef());
- else
- {
- context->PSSetSamplers(bindingIndex, 1, detail.m_samplerState.readRef());
- context->VSSetSamplers(bindingIndex, 1, detail.m_samplerState.readRef());
- }
- break;
- }
- default:
- {
- assert(!"Not implemented");
- return;
- }
- }
- }
-}
-
-void D3D11Renderer::setBindingState(BindingState* state)
-{
- m_currentBindings = static_cast<BindingStateImpl*>(state);
-}
-
-} // renderer_test
diff --git a/tools/render-test/render-d3d11.h b/tools/render-test/render-d3d11.h
deleted file mode 100644
index 59142731d..000000000
--- a/tools/render-test/render-d3d11.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// render-d3d11.h
-#pragma once
-
-namespace renderer_test {
-
-class Renderer;
-
-Renderer* createD3D11Renderer();
-
-} // renderer_test
diff --git a/tools/render-test/render-d3d12.cpp b/tools/render-test/render-d3d12.cpp
deleted file mode 100644
index 7603332b4..000000000
--- a/tools/render-test/render-d3d12.cpp
+++ /dev/null
@@ -1,2467 +0,0 @@
-// render-d3d12.cpp
-#define _CRT_SECURE_NO_WARNINGS
-
-#include "render-d3d12.h"
-
-#include "options.h"
-#include "render.h"
-
-#include "surface.h"
-
-// In order to use the Slang API, we need to include its header
-
-#include <slang.h>
-
-// We will be rendering with Direct3D 12, so we need to include
-// the Windows and D3D12 headers
-
-#define WIN32_LEAN_AND_MEAN
-#define NOMINMAX
-#include <Windows.h>
-#undef WIN32_LEAN_AND_MEAN
-#undef NOMINMAX
-
-#include <dxgi1_4.h>
-#include <d3d12.h>
-#include <d3dcompiler.h>
-
-#include "../../slang-com-ptr.h"
-
-#include "resource-d3d12.h"
-#include "descriptor-heap-d3d12.h"
-#include "circular-resource-heap-d3d12.h"
-
-#include "d3d-util.h"
-
-// We will use the C standard library just for printing error messages.
-#include <stdio.h>
-
-#ifdef _MSC_VER
-#include <stddef.h>
-#if (_MSC_VER < 1900)
-#define snprintf sprintf_s
-#endif
-#endif
-//
-
-#define ENABLE_DEBUG_LAYER 1
-
-namespace renderer_test {
-using namespace Slang;
-
-class D3D12Renderer : public Renderer
-{
-public:
- // 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& surfaceOut) 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::DirectX12; }
-
- ~D3D12Renderer();
-
-protected:
- static const Int kMaxNumRenderFrames = 4;
- static const Int kMaxNumRenderTargets = 3;
-
- struct Submitter
- {
- virtual void setRootConstantBufferView(int index, D3D12_GPU_VIRTUAL_ADDRESS gpuBufferLocation) = 0;
- virtual void setRootDescriptorTable(int index, D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor) = 0;
- virtual void setRootSignature(ID3D12RootSignature* rootSignature) = 0;
- };
-
- struct FrameInfo
- {
- FrameInfo() :m_fenceValue(0) {}
- void reset()
- {
- m_commandAllocator.setNull();
- }
- ComPtr<ID3D12CommandAllocator> m_commandAllocator; ///< The command allocator for this frame
- UINT64 m_fenceValue; ///< The fence value when rendering this Frame is complete
- };
-
- class ShaderProgramImpl: public ShaderProgram
- {
- public:
- PipelineType m_pipelineType;
- List<uint8_t> m_vertexShader;
- List<uint8_t> m_pixelShader;
- List<uint8_t> m_computeShader;
- };
-
- class BufferResourceImpl: public BufferResource
- {
- public:
- typedef BufferResource Parent;
-
- enum class BackingStyle
- {
- Unknown,
- ResourceBacked, ///< The contents is only held within the resource
- MemoryBacked, ///< The current contents is held in m_memory and copied to GPU every time it's used (typically used for constant buffers)
- };
-
- void bindConstantBufferView(D3D12CircularResourceHeap& circularHeap, int index, Submitter* submitter) const
- {
- switch (m_backingStyle)
- {
- case BackingStyle::MemoryBacked:
- {
- const size_t bufferSize = m_memory.Count();
- D3D12CircularResourceHeap::Cursor cursor = circularHeap.allocateConstantBuffer(bufferSize);
- ::memcpy(cursor.m_position, m_memory.Buffer(), bufferSize);
- // Set the constant buffer
- submitter->setRootConstantBufferView(index, circularHeap.getGpuHandle(cursor));
- break;
- }
- case BackingStyle::ResourceBacked:
- {
- // Set the constant buffer
- submitter->setRootConstantBufferView(index, m_resource.getResource()->GetGPUVirtualAddress());
- break;
- }
- default: break;
- }
- }
-
- BufferResourceImpl(Resource::Usage initialUsage, const Desc& desc):
- Parent(desc),
- m_mapFlavor(MapFlavor::HostRead),
- m_initialUsage(initialUsage)
- {
- }
-
- static BackingStyle _calcResourceBackingStyle(Usage usage)
- {
- switch (usage)
- {
- case Usage::ConstantBuffer: return BackingStyle::MemoryBacked;
- default: return BackingStyle::ResourceBacked;
- }
- }
-
- BackingStyle m_backingStyle; ///< How the resource is 'backed' - either as a resource or cpu memory. Cpu memory is typically used for constant buffers.
- D3D12Resource m_resource; ///< The resource typically in gpu memory
- D3D12Resource m_uploadResource; ///< If the resource can be written to, and is in gpu memory (ie not Memory backed), will have upload resource
-
- Usage m_initialUsage;
-
- List<uint8_t> m_memory; ///< Cpu memory buffer, used if the m_backingStyle is MemoryBacked
- MapFlavor m_mapFlavor; ///< If the resource is mapped holds the current mapping flavor
- };
-
- class TextureResourceImpl: public TextureResource
- {
- public:
- typedef TextureResource Parent;
-
- TextureResourceImpl(const Desc& desc):
- Parent(desc)
- {
- }
-
- D3D12Resource m_resource;
- };
-
- class InputLayoutImpl: public InputLayout
- {
- public:
- List<D3D12_INPUT_ELEMENT_DESC> m_elements;
- List<char> m_text; ///< Holds all strings to keep in scope
- };
-
- struct BindingDetail
- {
- int m_srvIndex = -1;
- int m_uavIndex = -1;
- int m_samplerIndex = -1;
- };
-
- class BindingStateImpl: public BindingState
- {
- public:
- typedef BindingState Parent;
-
- Result init(ID3D12Device* device)
- {
- // Set up descriptor heaps
- SLANG_RETURN_ON_FAIL(m_viewHeap.init(device, 256, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE));
- SLANG_RETURN_ON_FAIL(m_samplerHeap.init(device, 16, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE));
- return SLANG_OK;
- }
-
- /// Ctor
- BindingStateImpl(const Desc& desc) :
- Parent(desc)
- {}
-
- List<BindingDetail> m_bindingDetails; ///< These match 1-1 to the bindings in the m_desc
-
- D3D12DescriptorHeap m_viewHeap; ///< Cbv, Srv, Uav
- D3D12DescriptorHeap m_samplerHeap; ///< Heap for samplers
- };
-
- class RenderState: public RefObject
- {
- public:
- D3D12_PRIMITIVE_TOPOLOGY_TYPE m_primitiveTopologyType;
- RefPtr<BindingStateImpl> m_bindingState;
- RefPtr<InputLayoutImpl> m_inputLayout;
- RefPtr<ShaderProgramImpl> m_shaderProgram;
-
- ComPtr<ID3D12RootSignature> m_rootSignature;
- ComPtr<ID3D12PipelineState> m_pipelineState;
- };
-
- struct BoundVertexBuffer
- {
- RefPtr<BufferResourceImpl> m_buffer;
- int m_stride;
- int m_offset;
- };
-
- struct BindParameters
- {
- enum
- {
- kMaxRanges = 16,
- kMaxParameters = 32
- };
-
- D3D12_DESCRIPTOR_RANGE& nextRange() { return m_ranges[m_rangeIndex++]; }
- D3D12_ROOT_PARAMETER& nextParameter() { return m_parameters[m_paramIndex++]; }
-
- BindParameters():
- m_rangeIndex(0),
- m_paramIndex(0)
- {}
-
- D3D12_DESCRIPTOR_RANGE m_ranges[kMaxRanges];
- int m_rangeIndex;
- D3D12_ROOT_PARAMETER m_parameters[kMaxParameters];
- int m_paramIndex;
- };
-
- struct GraphicsSubmitter : public Submitter
- {
- virtual void setRootConstantBufferView(int index, D3D12_GPU_VIRTUAL_ADDRESS gpuBufferLocation) override
- {
- m_commandList->SetGraphicsRootConstantBufferView(index, gpuBufferLocation);
- }
- virtual void setRootDescriptorTable(int index, D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor) override
- {
- m_commandList->SetGraphicsRootDescriptorTable(index, baseDescriptor);
- }
- void setRootSignature(ID3D12RootSignature* rootSignature)
- {
- m_commandList->SetGraphicsRootSignature(rootSignature);
- }
-
- GraphicsSubmitter(ID3D12GraphicsCommandList* commandList):
- m_commandList(commandList)
- {
- }
-
- ID3D12GraphicsCommandList* m_commandList;
- };
-
- struct ComputeSubmitter : public Submitter
- {
- virtual void setRootConstantBufferView(int index, D3D12_GPU_VIRTUAL_ADDRESS gpuBufferLocation) override
- {
- m_commandList->SetComputeRootConstantBufferView(index, gpuBufferLocation);
- }
- virtual void setRootDescriptorTable(int index, D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor) override
- {
- m_commandList->SetComputeRootDescriptorTable(index, baseDescriptor);
- }
- void setRootSignature(ID3D12RootSignature* rootSignature)
- {
- m_commandList->SetComputeRootSignature(rootSignature);
- }
-
- ComputeSubmitter(ID3D12GraphicsCommandList* commandList) :
- m_commandList(commandList)
- {
- }
-
- ID3D12GraphicsCommandList* m_commandList;
- };
-
- static PROC loadProc(HMODULE module, char const* name);
- Result createFrameResources();
- /// Blocks until gpu has completed all work
- void releaseFrameResources();
-
- Result createBuffer(const D3D12_RESOURCE_DESC& resourceDesc, const void* srcData, D3D12Resource& uploadResource, D3D12_RESOURCE_STATES finalState, D3D12Resource& resourceOut);
-
- void beginRender();
-
- void endRender();
-
- void submitGpuWorkAndWait();
- void _resetCommandList();
-
- Result captureTextureToSurface(D3D12Resource& resource, Surface& surfaceOut);
-
- FrameInfo& getFrame() { return m_frameInfos[m_frameIndex]; }
- const FrameInfo& getFrame() const { return m_frameInfos[m_frameIndex]; }
-
- ID3D12GraphicsCommandList* getCommandList() const { return m_commandList; }
-
- RenderState* calcRenderState();
- /// From current bindings calculate the root signature and pipeline state
- Result calcGraphicsPipelineState(ComPtr<ID3D12RootSignature>& sigOut, ComPtr<ID3D12PipelineState>& pipelineStateOut);
- Result calcComputePipelineState(ComPtr<ID3D12RootSignature>& signatureOut, ComPtr<ID3D12PipelineState>& pipelineStateOut);
-
- Result _bindRenderState(RenderState* renderState, ID3D12GraphicsCommandList* commandList, Submitter* submitter);
-
- Result _calcBindParameters(BindParameters& params);
- RenderState* findRenderState(PipelineType pipelineType);
-
- PFN_D3D12_SERIALIZE_ROOT_SIGNATURE m_D3D12SerializeRootSignature = nullptr;
-
- D3D12CircularResourceHeap m_circularResourceHeap;
-
- int m_commandListOpenCount = 0; ///< If >0 the command list should be open
-
- List<BoundVertexBuffer> m_boundVertexBuffers;
-
- RefPtr<ShaderProgramImpl> m_boundShaderProgram;
- RefPtr<InputLayoutImpl> m_boundInputLayout;
- RefPtr<BindingStateImpl> m_boundBindingState;
-
- DXGI_FORMAT m_targetFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
- DXGI_FORMAT m_depthStencilFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
- bool m_hasVsync = true;
- bool m_isFullSpeed = false;
- bool m_allowFullScreen = false;
- bool m_isMultiSampled = false;
- int m_numTargetSamples = 1; ///< The number of multi sample samples
- int m_targetSampleQuality = 0; ///< The multi sample quality
-
- Desc m_desc;
-
- bool m_isInitialized = false;
-
- D3D12_PRIMITIVE_TOPOLOGY_TYPE m_primitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
- D3D12_PRIMITIVE_TOPOLOGY m_primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
-
- float m_clearColor[4] = { 0, 0, 0, 0 };
-
- D3D12_VIEWPORT m_viewport = {};
-
- ComPtr<ID3D12Debug> m_dxDebug;
-
- ComPtr<ID3D12Device> m_device;
- ComPtr<IDXGISwapChain3> m_swapChain;
- ComPtr<ID3D12CommandQueue> m_commandQueue;
- ComPtr<ID3D12DescriptorHeap> m_rtvHeap;
- ComPtr<ID3D12GraphicsCommandList> m_commandList;
-
- D3D12_RECT m_scissorRect = {};
-
- List<RefPtr<RenderState> > m_renderStates; ///< Holds list of all render state combinations
- RenderState* m_currentRenderState = nullptr; ///< The current combination
-
- UINT m_rtvDescriptorSize = 0;
-
- ComPtr<ID3D12DescriptorHeap> m_dsvHeap;
- UINT m_dsvDescriptorSize = 0;
-
- // Synchronization objects.
- D3D12CounterFence m_fence;
-
- HANDLE m_swapChainWaitableObject;
-
- // Frame specific data
- int m_numRenderFrames = 0;
- UINT m_frameIndex = 0;
- FrameInfo m_frameInfos[kMaxNumRenderFrames];
-
- int m_numRenderTargets = 2;
- int m_renderTargetIndex = 0;
-
- D3D12Resource* m_backBuffers[kMaxNumRenderTargets];
- D3D12Resource* m_renderTargets[kMaxNumRenderTargets];
-
- D3D12Resource m_backBufferResources[kMaxNumRenderTargets];
- D3D12Resource m_renderTargetResources[kMaxNumRenderTargets];
-
- D3D12Resource m_depthStencil;
- D3D12_CPU_DESCRIPTOR_HANDLE m_depthStencilView = {};
-
- int32_t m_depthStencilUsageFlags = 0; ///< D3DUtil::UsageFlag combination for depth stencil
- int32_t m_targetUsageFlags = 0; ///< D3DUtil::UsageFlag combination for target
-
- HWND m_hwnd = nullptr;
-};
-
-Renderer* createD3D12Renderer()
-{
- return new D3D12Renderer;
-}
-
-/* static */PROC D3D12Renderer::loadProc(HMODULE module, char const* name)
-{
- PROC proc = ::GetProcAddress(module, name);
- if (!proc)
- {
- fprintf(stderr, "error: failed load symbol '%s'\n", name);
- return nullptr;
- }
- return proc;
-}
-
-void D3D12Renderer::releaseFrameResources()
-{
- // https://msdn.microsoft.com/en-us/library/windows/desktop/bb174577%28v=vs.85%29.aspx
-
- // Release the resources holding references to the swap chain (requirement of
- // IDXGISwapChain::ResizeBuffers) and reset the frame fence values to the
- // current fence value.
- for (int i = 0; i < m_numRenderFrames; i++)
- {
- FrameInfo& info = m_frameInfos[i];
- info.reset();
- info.m_fenceValue = m_fence.getCurrentValue();
- }
- for (int i = 0; i < m_numRenderTargets; i++)
- {
- m_backBuffers[i]->setResourceNull();
- m_renderTargets[i]->setResourceNull();
- }
-}
-
-void D3D12Renderer::waitForGpu()
-{
- m_fence.nextSignalAndWait(m_commandQueue);
-}
-
-D3D12Renderer::~D3D12Renderer()
-{
- if (m_isInitialized)
- {
- // Ensure that the GPU is no longer referencing resources that are about to be
- // cleaned up by the destructor.
- waitForGpu();
- }
-}
-
-static void _initSrvDesc(Resource::Type resourceType, const TextureResource::Desc& textureDesc, const D3D12_RESOURCE_DESC& desc, DXGI_FORMAT pixelFormat, D3D12_SHADER_RESOURCE_VIEW_DESC& descOut)
-{
- // create SRV
- descOut = D3D12_SHADER_RESOURCE_VIEW_DESC();
-
- descOut.Format = (pixelFormat == DXGI_FORMAT_UNKNOWN) ? D3DUtil::calcFormat(D3DUtil::USAGE_SRV, desc.Format) : pixelFormat;
- descOut.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
- if (desc.DepthOrArraySize == 1)
- {
- switch (desc.Dimension)
- {
- case D3D12_RESOURCE_DIMENSION_TEXTURE1D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; break;
- case D3D12_RESOURCE_DIMENSION_TEXTURE2D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; break;
- case D3D12_RESOURCE_DIMENSION_TEXTURE3D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; break;
- default: assert(!"Unknown dimension");
- }
-
- descOut.Texture2D.MipLevels = desc.MipLevels;
- descOut.Texture2D.MostDetailedMip = 0;
- descOut.Texture2D.PlaneSlice = 0;
- descOut.Texture2D.ResourceMinLODClamp = 0.0f;
- }
- else if (resourceType == Resource::Type::TextureCube)
- {
- if (textureDesc.arraySize > 1)
- {
- descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
-
- descOut.TextureCubeArray.NumCubes = textureDesc.arraySize;
- descOut.TextureCubeArray.First2DArrayFace = 0;
- descOut.TextureCubeArray.MipLevels = desc.MipLevels;
- descOut.TextureCubeArray.MostDetailedMip = 0;
- descOut.TextureCubeArray.ResourceMinLODClamp = 0;
- }
- else
- {
- descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
-
- descOut.TextureCube.MipLevels = desc.MipLevels;
- descOut.TextureCube.MostDetailedMip = 0;
- descOut.TextureCube.ResourceMinLODClamp = 0;
- }
- }
- else
- {
- assert(desc.DepthOrArraySize > 1);
-
- switch (desc.Dimension)
- {
- case D3D12_RESOURCE_DIMENSION_TEXTURE1D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; break;
- case D3D12_RESOURCE_DIMENSION_TEXTURE2D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; break;
- case D3D12_RESOURCE_DIMENSION_TEXTURE3D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; break;
-
- default: assert(!"Unknown dimension");
- }
-
- descOut.Texture2DArray.ArraySize = desc.DepthOrArraySize;
- descOut.Texture2DArray.MostDetailedMip = 0;
- descOut.Texture2DArray.MipLevels = desc.MipLevels;
- descOut.Texture2DArray.FirstArraySlice = 0;
- descOut.Texture2DArray.PlaneSlice = 0;
- descOut.Texture2DArray.ResourceMinLODClamp = 0;
- }
-}
-
-static void _initBufferResourceDesc(size_t bufferSize, D3D12_RESOURCE_DESC& out)
-{
- out = {};
-
- out.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
- out.Alignment = 0;
- out.Width = bufferSize;
- out.Height = 1;
- out.DepthOrArraySize = 1;
- out.MipLevels = 1;
- out.Format = DXGI_FORMAT_UNKNOWN;
- out.SampleDesc.Count = 1;
- out.SampleDesc.Quality = 0;
- out.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
- out.Flags = D3D12_RESOURCE_FLAG_NONE;
-}
-
-Result D3D12Renderer::createBuffer(const D3D12_RESOURCE_DESC& resourceDesc, const void* srcData, D3D12Resource& uploadResource, D3D12_RESOURCE_STATES finalState, D3D12Resource& resourceOut)
-{
- const size_t bufferSize = size_t(resourceDesc.Width);
-
- {
- D3D12_HEAP_PROPERTIES heapProps;
- heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
-
- const D3D12_RESOURCE_STATES initialState = srcData ? D3D12_RESOURCE_STATE_COPY_DEST : finalState;
-
- SLANG_RETURN_ON_FAIL(resourceOut.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, resourceDesc, initialState, nullptr));
- }
-
- {
- D3D12_HEAP_PROPERTIES heapProps;
- heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
-
- D3D12_RESOURCE_DESC uploadResourceDesc(resourceDesc);
- uploadResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
-
- SLANG_RETURN_ON_FAIL(uploadResource.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, uploadResourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr));
- }
-
- if (srcData)
- {
- // Copy data to the intermediate upload heap and then schedule a copy
- // from the upload heap to the vertex buffer.
- UINT8* dstData;
- D3D12_RANGE readRange = {}; // We do not intend to read from this resource on the CPU.
-
- ID3D12Resource* dxUploadResource = uploadResource.getResource();
-
- SLANG_RETURN_ON_FAIL(dxUploadResource->Map(0, &readRange, reinterpret_cast<void**>(&dstData)));
- ::memcpy(dstData, srcData, bufferSize);
- dxUploadResource->Unmap(0, nullptr);
-
- m_commandList->CopyBufferRegion(resourceOut, 0, uploadResource, 0, bufferSize);
-
- // Make sure it's in the right state
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- resourceOut.transition(finalState, submitter);
- }
-
- submitGpuWorkAndWait();
- }
-
- return SLANG_OK;
-}
-
-void D3D12Renderer::_resetCommandList()
-{
- const FrameInfo& frame = getFrame();
-
- ID3D12GraphicsCommandList* commandList = getCommandList();
- commandList->Reset(frame.m_commandAllocator, nullptr);
-
- D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = { m_rtvHeap->GetCPUDescriptorHandleForHeapStart().ptr + m_renderTargetIndex * m_rtvDescriptorSize };
- if (m_depthStencil)
- {
- commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &m_depthStencilView);
- }
- else
- {
- commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);
- }
-
- // Set necessary state.
- commandList->RSSetViewports(1, &m_viewport);
- commandList->RSSetScissorRects(1, &m_scissorRect);
-}
-
-void D3D12Renderer::beginRender()
-{
- // Should currently not be open!
- assert(m_commandListOpenCount == 0);
-
- m_circularResourceHeap.updateCompleted();
-
- getFrame().m_commandAllocator->Reset();
-
- _resetCommandList();
-
- // Indicate that the render target needs to be writable
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- m_renderTargets[m_renderTargetIndex]->transition(D3D12_RESOURCE_STATE_RENDER_TARGET, submitter);
- }
-
- m_commandListOpenCount = 1;
-}
-
-void D3D12Renderer::endRender()
-{
- assert(m_commandListOpenCount == 1);
-
- {
- const UInt64 signalValue = m_fence.nextSignal(m_commandQueue);
- m_circularResourceHeap.addSync(signalValue);
- }
-
- D3D12Resource& backBuffer = *m_backBuffers[m_renderTargetIndex];
- if (m_isMultiSampled)
- {
- // MSAA resolve
- D3D12Resource& renderTarget = *m_renderTargets[m_renderTargetIndex];
- assert(&renderTarget != &backBuffer);
- // Barriers to wait for the render target, and the backbuffer to be in correct state
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- renderTarget.transition(D3D12_RESOURCE_STATE_RESOLVE_SOURCE, submitter);
- backBuffer.transition(D3D12_RESOURCE_STATE_RESOLVE_DEST, submitter);
- }
-
- // Do the resolve...
- m_commandList->ResolveSubresource(backBuffer, 0, renderTarget, 0, m_targetFormat);
- }
-
- // Make the back buffer presentable
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- backBuffer.transition(D3D12_RESOURCE_STATE_PRESENT, submitter);
- }
-
- SLANG_ASSERT_VOID_ON_FAIL(m_commandList->Close());
-
- {
- // Execute the command list.
- ID3D12CommandList* commandLists[] = { m_commandList };
- m_commandQueue->ExecuteCommandLists(SLANG_COUNT_OF(commandLists), commandLists);
- }
-
- assert(m_commandListOpenCount == 1);
- // Must be 0
- m_commandListOpenCount = 0;
-}
-
-void D3D12Renderer::submitGpuWork()
-{
- assert(m_commandListOpenCount);
- ID3D12GraphicsCommandList* commandList = getCommandList();
-
- SLANG_ASSERT_VOID_ON_FAIL(commandList->Close());
- {
- // Execute the command list.
- ID3D12CommandList* commandLists[] = { commandList };
- m_commandQueue->ExecuteCommandLists(SLANG_COUNT_OF(commandLists), commandLists);
- }
-
- // Reset the render target
- _resetCommandList();
-}
-
-void D3D12Renderer::submitGpuWorkAndWait()
-{
- submitGpuWork();
- waitForGpu();
-}
-
-Result D3D12Renderer::captureTextureToSurface(D3D12Resource& resource, Surface& surfaceOut)
-{
- const D3D12_RESOURCE_STATES initialState = resource.getState();
-
- const D3D12_RESOURCE_DESC desc = resource.getResource()->GetDesc();
-
- // Don't bother supporting MSAA for right now
- if (desc.SampleDesc.Count > 1)
- {
- fprintf(stderr, "ERROR: cannot capture multi-sample texture\n");
- return SLANG_FAIL;
- }
-
- size_t bytesPerPixel = sizeof(uint32_t);
- size_t rowPitch = int(desc.Width) * bytesPerPixel;
- size_t bufferSize = rowPitch * int(desc.Height);
-
- D3D12Resource stagingResource;
- {
- D3D12_RESOURCE_DESC stagingDesc;
- _initBufferResourceDesc(bufferSize, stagingDesc);
-
- D3D12_HEAP_PROPERTIES heapProps;
- heapProps.Type = D3D12_HEAP_TYPE_READBACK;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
-
- SLANG_RETURN_ON_FAIL(stagingResource.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, stagingDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr));
- }
-
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- resource.transition(D3D12_RESOURCE_STATE_COPY_SOURCE, submitter);
- }
-
- // Do the copy
- {
- D3D12_TEXTURE_COPY_LOCATION srcLoc;
- srcLoc.pResource = resource;
- srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
- srcLoc.SubresourceIndex = 0;
-
- D3D12_TEXTURE_COPY_LOCATION dstLoc;
- dstLoc.pResource = stagingResource;
- dstLoc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
- dstLoc.PlacedFootprint.Offset = 0;
- dstLoc.PlacedFootprint.Footprint.Format = desc.Format;
- dstLoc.PlacedFootprint.Footprint.Width = UINT(desc.Width);
- dstLoc.PlacedFootprint.Footprint.Height = UINT(desc.Height);
- dstLoc.PlacedFootprint.Footprint.Depth = 1;
- dstLoc.PlacedFootprint.Footprint.RowPitch = UINT(rowPitch);
-
- m_commandList->CopyTextureRegion(&dstLoc, 0, 0, 0, &srcLoc, nullptr);
- }
-
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- resource.transition(initialState, submitter);
- }
-
- // Submit the copy, and wait for copy to complete
- submitGpuWorkAndWait();
-
- {
- ID3D12Resource* dxResource = stagingResource;
-
- UINT8* data;
- D3D12_RANGE readRange = {0, bufferSize};
-
- SLANG_RETURN_ON_FAIL(dxResource->Map(0, &readRange, reinterpret_cast<void**>(&data)));
-
- Result res = surfaceOut.set(int(desc.Width), int(desc.Height), Format::RGBA_Unorm_UInt8, int(rowPitch), data, SurfaceAllocator::getMallocAllocator());
-
- dxResource->Unmap(0, nullptr);
- return res;
- }
-}
-
-Result D3D12Renderer::calcComputePipelineState(ComPtr<ID3D12RootSignature>& signatureOut, ComPtr<ID3D12PipelineState>& pipelineStateOut)
-{
- BindParameters bindParameters;
- _calcBindParameters(bindParameters);
-
- ComPtr<ID3D12RootSignature> rootSignature;
- ComPtr<ID3D12PipelineState> pipelineState;
-
- {
- D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc;
- rootSignatureDesc.NumParameters = bindParameters.m_paramIndex;
- rootSignatureDesc.pParameters = bindParameters.m_parameters;
- rootSignatureDesc.NumStaticSamplers = 0;
- rootSignatureDesc.pStaticSamplers = nullptr;
- rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;
-
- ComPtr<ID3DBlob> signature;
- ComPtr<ID3DBlob> error;
- SLANG_RETURN_ON_FAIL(m_D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, signature.writeRef(), error.writeRef()));
- SLANG_RETURN_ON_FAIL(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(rootSignature.writeRef())));
- }
-
- {
- // Describe and create the compute pipeline state object
- D3D12_COMPUTE_PIPELINE_STATE_DESC computeDesc = {};
- computeDesc.pRootSignature = rootSignature;
- computeDesc.CS = { m_boundShaderProgram->m_computeShader.Buffer(), m_boundShaderProgram->m_computeShader.Count() };
- SLANG_RETURN_ON_FAIL(m_device->CreateComputePipelineState(&computeDesc, IID_PPV_ARGS(pipelineState.writeRef())));
- }
-
- signatureOut.swap(rootSignature);
- pipelineStateOut.swap(pipelineState);
-
- return SLANG_OK;
-}
-
-Result D3D12Renderer::calcGraphicsPipelineState(ComPtr<ID3D12RootSignature>& signatureOut, ComPtr<ID3D12PipelineState>& pipelineStateOut)
-{
- BindParameters bindParameters;
- _calcBindParameters(bindParameters);
-
- ComPtr<ID3D12RootSignature> rootSignature;
- ComPtr<ID3D12PipelineState> pipelineState;
-
- {
- // Deny unnecessary access to certain pipeline stages
- D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc;
- rootSignatureDesc.NumParameters = bindParameters.m_paramIndex;
- rootSignatureDesc.pParameters = bindParameters.m_parameters;
- rootSignatureDesc.NumStaticSamplers = 0;
- rootSignatureDesc.pStaticSamplers = nullptr;
- rootSignatureDesc.Flags = m_boundInputLayout ? D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT : D3D12_ROOT_SIGNATURE_FLAG_NONE;
-
- ComPtr<ID3DBlob> signature;
- ComPtr<ID3DBlob> error;
- SLANG_RETURN_ON_FAIL(m_D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, signature.writeRef(), error.writeRef()));
- SLANG_RETURN_ON_FAIL(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(rootSignature.writeRef())));
- }
-
- {
- // Describe and create the graphics pipeline state object (PSO)
- D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
-
- psoDesc.pRootSignature = rootSignature;
-
- psoDesc.VS = { m_boundShaderProgram->m_vertexShader.Buffer(), m_boundShaderProgram->m_vertexShader.Count() };
- psoDesc.PS = { m_boundShaderProgram->m_pixelShader.Buffer(), m_boundShaderProgram->m_pixelShader.Count() };
-
- {
- psoDesc.InputLayout = { m_boundInputLayout->m_elements.Buffer(), UINT(m_boundInputLayout->m_elements.Count()) };
- psoDesc.PrimitiveTopologyType = m_primitiveTopologyType;
-
- {
- const int numRenderTargets = m_boundBindingState ? m_boundBindingState->getDesc().m_numRenderTargets : 1;
-
- psoDesc.DSVFormat = m_depthStencilFormat;
- psoDesc.NumRenderTargets = numRenderTargets;
- for (Int i = 0; i < numRenderTargets; i++)
- {
- psoDesc.RTVFormats[i] = m_targetFormat;
- }
-
- psoDesc.SampleDesc.Count = 1;
- psoDesc.SampleDesc.Quality = 0;
-
- psoDesc.SampleMask = UINT_MAX;
- }
-
- {
- auto& rs = psoDesc.RasterizerState;
- rs.FillMode = D3D12_FILL_MODE_SOLID;
- rs.CullMode = D3D12_CULL_MODE_NONE;
- rs.FrontCounterClockwise = FALSE;
- rs.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
- rs.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
- rs.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
- rs.DepthClipEnable = TRUE;
- rs.MultisampleEnable = FALSE;
- rs.AntialiasedLineEnable = FALSE;
- rs.ForcedSampleCount = 0;
- rs.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
- }
-
- {
- D3D12_BLEND_DESC& blend = psoDesc.BlendState;
-
- blend.AlphaToCoverageEnable = FALSE;
- blend.IndependentBlendEnable = FALSE;
- const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc =
- {
- FALSE,FALSE,
- D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
- D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
- D3D12_LOGIC_OP_NOOP,
- D3D12_COLOR_WRITE_ENABLE_ALL,
- };
- for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
- {
- blend.RenderTarget[i] = defaultRenderTargetBlendDesc;
- }
- }
-
- {
- auto& ds = psoDesc.DepthStencilState;
-
- ds.DepthEnable = FALSE;
- ds.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
- ds.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS;
- //ds.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
- ds.StencilEnable = FALSE;
- ds.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;
- ds.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;
- const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =
- {
- D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS
- };
- ds.FrontFace = defaultStencilOp;
- ds.BackFace = defaultStencilOp;
- }
- }
-
- psoDesc.PrimitiveTopologyType = m_primitiveTopologyType;
-
- SLANG_RETURN_ON_FAIL(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(pipelineState.writeRef())));
- }
-
- signatureOut.swap(rootSignature);
- pipelineStateOut.swap(pipelineState);
-
- return SLANG_OK;
-}
-
-D3D12Renderer::RenderState* D3D12Renderer::findRenderState(PipelineType pipelineType)
-{
- switch (pipelineType)
- {
- case PipelineType::Compute:
- {
- // Check if current state is a match
- if (m_currentRenderState)
- {
- if (m_currentRenderState->m_bindingState == m_boundBindingState &&
- m_currentRenderState->m_shaderProgram == m_boundShaderProgram)
- {
- return m_currentRenderState;
- }
- }
-
- const int num = int(m_renderStates.Count());
- for (int i = 0; i < num; i++)
- {
- RenderState* renderState = m_renderStates[i];
- if (renderState->m_bindingState == m_boundBindingState &&
- renderState->m_shaderProgram == m_boundShaderProgram)
- {
- return renderState;
- }
- }
- break;
- }
- case PipelineType::Graphics:
- {
- if (m_currentRenderState)
- {
- if (m_currentRenderState->m_bindingState == m_boundBindingState &&
- m_currentRenderState->m_inputLayout == m_boundInputLayout &&
- m_currentRenderState->m_shaderProgram == m_boundShaderProgram &&
- m_currentRenderState->m_primitiveTopologyType == m_primitiveTopologyType)
- {
- return m_currentRenderState;
- }
- }
- // See if matches one in the list
- {
- const int num = int(m_renderStates.Count());
- for (int i = 0; i < num; i++)
- {
- RenderState* renderState = m_renderStates[i];
- if (renderState->m_bindingState == m_boundBindingState &&
- renderState->m_inputLayout == m_boundInputLayout &&
- renderState->m_shaderProgram == m_boundShaderProgram &&
- renderState->m_primitiveTopologyType == m_primitiveTopologyType)
- {
- // Okay we have a match
- return renderState;
- }
- }
- }
- break;
- }
- default: break;
- }
- return nullptr;
-}
-
-D3D12Renderer::RenderState* D3D12Renderer::calcRenderState()
-{
- if (!m_boundShaderProgram)
- {
- return nullptr;
- }
- m_currentRenderState = findRenderState(m_boundShaderProgram->m_pipelineType);
- if (m_currentRenderState)
- {
- return m_currentRenderState;
- }
-
- ComPtr<ID3D12RootSignature> rootSignature;
- ComPtr<ID3D12PipelineState> pipelineState;
-
- switch (m_boundShaderProgram->m_pipelineType)
- {
- case PipelineType::Compute:
- {
- if (SLANG_FAILED(calcComputePipelineState(rootSignature, pipelineState)))
- {
- return nullptr;
- }
- break;
- }
- case PipelineType::Graphics:
- {
- if (SLANG_FAILED(calcGraphicsPipelineState(rootSignature, pipelineState)))
- {
- return nullptr;
- }
- break;
- }
- default: return nullptr;
- }
-
- RenderState* renderState = new RenderState;
-
- renderState->m_primitiveTopologyType = m_primitiveTopologyType;
- renderState->m_bindingState = m_boundBindingState;
- renderState->m_inputLayout = m_boundInputLayout;
- renderState->m_shaderProgram = m_boundShaderProgram;
-
- renderState->m_rootSignature.swap(rootSignature);
- renderState->m_pipelineState.swap(pipelineState);
-
- m_renderStates.Add(renderState);
-
- m_currentRenderState = renderState;
-
- return renderState;
-}
-
-Result D3D12Renderer::_calcBindParameters(BindParameters& params)
-{
- int numConstantBuffers = 0;
- {
- if (m_boundBindingState)
- {
- const int numBoundConstantBuffers = numConstantBuffers;
-
- const BindingState::Desc& bindingStateDesc = m_boundBindingState->getDesc();
-
- const auto& bindings = bindingStateDesc.m_bindings;
- const auto& details = m_boundBindingState->m_bindingDetails;
-
- const int numBindings = int(bindings.Count());
-
- for (int i = 0; i < numBindings; i++)
- {
- const auto& binding = bindings[i];
- const auto& detail = details[i];
-
- const int bindingIndex = binding.registerRange.getSingleIndex();
-
- if (binding.bindingType == BindingType::Buffer)
- {
- assert(binding.resource && binding.resource->isBuffer());
- if (binding.resource->canBind(Resource::BindFlag::ConstantBuffer))
- {
- // Make sure it's not overlapping the ones we just statically defined
- //assert(binding.m_binding < numBoundConstantBuffers);
-
- D3D12_ROOT_PARAMETER& param = params.nextParameter();
- param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
- param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
-
- D3D12_ROOT_DESCRIPTOR& descriptor = param.Descriptor;
- descriptor.ShaderRegister = bindingIndex;
- descriptor.RegisterSpace = 0;
-
- numConstantBuffers++;
- }
- }
-
- if (detail.m_srvIndex >= 0)
- {
- D3D12_DESCRIPTOR_RANGE& range = params.nextRange();
-
- range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
- range.NumDescriptors = 1;
- range.BaseShaderRegister = bindingIndex;
- range.RegisterSpace = 0;
- range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
-
- D3D12_ROOT_PARAMETER& param = params.nextParameter();
-
- param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
-
- D3D12_ROOT_DESCRIPTOR_TABLE& table = param.DescriptorTable;
- table.NumDescriptorRanges = 1;
- table.pDescriptorRanges = &range;
- }
-
- if (detail.m_uavIndex >= 0)
- {
- D3D12_DESCRIPTOR_RANGE& range = params.nextRange();
-
- range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
- range.NumDescriptors = 1;
- range.BaseShaderRegister = bindingIndex;
- range.RegisterSpace = 0;
- range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
-
- D3D12_ROOT_PARAMETER& param = params.nextParameter();
-
- param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
-
- D3D12_ROOT_DESCRIPTOR_TABLE& table = param.DescriptorTable;
- table.NumDescriptorRanges = 1;
- table.pDescriptorRanges = &range;
- }
- }
- }
- }
-
- // All the samplers are in one continuous section of the sampler heap
- if (m_boundBindingState && m_boundBindingState->m_samplerHeap.getUsedSize() > 0)
- {
- D3D12_DESCRIPTOR_RANGE& range = params.nextRange();
-
- range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
- range.NumDescriptors = m_boundBindingState->m_samplerHeap.getUsedSize();
- range.BaseShaderRegister = 0;
- range.RegisterSpace = 0;
- range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
-
- D3D12_ROOT_PARAMETER& param = params.nextParameter();
-
- param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
-
- D3D12_ROOT_DESCRIPTOR_TABLE& table = param.DescriptorTable;
- table.NumDescriptorRanges = 1;
- table.pDescriptorRanges = &range;
- }
- return SLANG_OK;
-}
-
-Result D3D12Renderer::_bindRenderState(RenderState* renderState, ID3D12GraphicsCommandList* commandList, Submitter* submitter)
-{
- BindingStateImpl* bindingState = m_boundBindingState;
-
- submitter->setRootSignature(renderState->m_rootSignature);
- commandList->SetPipelineState(renderState->m_pipelineState);
-
- if (bindingState)
- {
- ID3D12DescriptorHeap* heaps[] =
- {
- bindingState->m_viewHeap.getHeap(),
- bindingState->m_samplerHeap.getHeap(),
- };
- commandList->SetDescriptorHeaps(SLANG_COUNT_OF(heaps), heaps);
- }
- else
- {
- commandList->SetDescriptorHeaps(0, nullptr);
- }
-
- {
- int index = 0;
-
- int numConstantBuffers = 0;
- {
- if (bindingState)
- {
- D3D12DescriptorHeap& heap = bindingState->m_viewHeap;
- const auto& details = bindingState->m_bindingDetails;
- const auto& bindings = bindingState->getDesc().m_bindings;
- const int numBindings = int(details.Count());
-
- for (int i = 0; i < numBindings; i++)
- {
- const auto& detail = details[i];
- const auto& binding = bindings[i];
-
- if (binding.bindingType == BindingType::Buffer)
- {
- assert(binding.resource && binding.resource->isBuffer());
- if (binding.resource->canBind(Resource::BindFlag::ConstantBuffer))
- {
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(binding.resource.Ptr());
- buffer->bindConstantBufferView(m_circularResourceHeap, index++, submitter);
- numConstantBuffers++;
- }
- }
-
- if (detail.m_srvIndex >= 0)
- {
- submitter->setRootDescriptorTable(index++, heap.getGpuHandle(detail.m_srvIndex));
- }
-
- if (detail.m_uavIndex >= 0)
- {
- submitter->setRootDescriptorTable(index++, heap.getGpuHandle(detail.m_uavIndex));
- }
- }
- }
- }
-
- if (bindingState && bindingState->m_samplerHeap.getUsedSize() > 0)
- {
- submitter->setRootDescriptorTable(index, bindingState->m_samplerHeap.getGpuStart());
- }
- }
-
- return SLANG_OK;
-}
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
-
-Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
-{
- m_hwnd = (HWND)inWindowHandle;
- // Rather than statically link against D3D, we load it dynamically.
-
- HMODULE d3dModule = LoadLibraryA("d3d12.dll");
- if (!d3dModule)
- {
- fprintf(stderr, "error: failed load 'd3d12.dll'\n");
- return SLANG_FAIL;
- }
-
- HMODULE dxgiModule = LoadLibraryA("Dxgi.dll");
- if (!dxgiModule)
- {
- fprintf(stderr, "error: failed load 'dxgi.dll'\n");
- return SLANG_FAIL;
- }
-
-
-#define LOAD_D3D_PROC(TYPE, NAME) \
- TYPE NAME##_ = (TYPE) loadProc(d3dModule, #NAME);
-#define LOAD_DXGI_PROC(TYPE, NAME) \
- TYPE NAME##_ = (TYPE) loadProc(dxgiModule, #NAME);
-
- UINT dxgiFactoryFlags = 0;
-
-#if ENABLE_DEBUG_LAYER
- {
- LOAD_D3D_PROC(PFN_D3D12_GET_DEBUG_INTERFACE, D3D12GetDebugInterface);
- if (D3D12GetDebugInterface_)
- {
- if (SUCCEEDED(D3D12GetDebugInterface_(IID_PPV_ARGS(m_dxDebug.writeRef()))))
- {
- m_dxDebug->EnableDebugLayer();
- dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
- }
- }
- }
-#endif
-
- m_D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)loadProc(d3dModule, "D3D12SerializeRootSignature");
- if (!m_D3D12SerializeRootSignature)
- {
- return SLANG_FAIL;
- }
-
- // Try and create DXGIFactory
- ComPtr<IDXGIFactory4> dxgiFactory;
- {
- typedef HRESULT(WINAPI *PFN_DXGI_CREATE_FACTORY_2)(UINT Flags, REFIID riid, _COM_Outptr_ void **ppFactory);
- LOAD_DXGI_PROC(PFN_DXGI_CREATE_FACTORY_2, CreateDXGIFactory2);
- if (!CreateDXGIFactory2_)
- {
- return SLANG_FAIL;
- }
- SLANG_RETURN_ON_FAIL(CreateDXGIFactory2_(dxgiFactoryFlags, IID_PPV_ARGS(dxgiFactory.writeRef())));
- }
-
- D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
-
- // Search for an adapter that meets our requirements
- ComPtr<IDXGIAdapter> adapter;
-
- LOAD_D3D_PROC(PFN_D3D12_CREATE_DEVICE, D3D12CreateDevice);
- if (!D3D12CreateDevice_)
- {
- return SLANG_FAIL;
- }
-
- const bool useWarp = false;
-
- if (useWarp)
- {
- SLANG_RETURN_ON_FAIL(dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.writeRef())));
- SLANG_RETURN_ON_FAIL(D3D12CreateDevice_(adapter, featureLevel, IID_PPV_ARGS(m_device.writeRef())));
- }
- else
- {
- UINT adapterCounter = 0;
- for (;;)
- {
- UINT adapterIndex = adapterCounter++;
-
- ComPtr<IDXGIAdapter1> candidateAdapter;
- if (dxgiFactory->EnumAdapters1(adapterIndex, candidateAdapter.writeRef()) == DXGI_ERROR_NOT_FOUND)
- break;
-
- DXGI_ADAPTER_DESC1 desc;
- candidateAdapter->GetDesc1(&desc);
-
- if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
- {
- // TODO: may want to allow software driver as fallback
- }
- else if (SUCCEEDED(D3D12CreateDevice_(candidateAdapter, featureLevel, IID_PPV_ARGS(m_device.writeRef()))))
- {
- // We found one!
- adapter = candidateAdapter;
- break;
- }
- }
- }
-
- if (!adapter)
- {
- // Couldn't find an adapter
- return SLANG_FAIL;
- }
-
- m_numRenderFrames = 3;
- m_numRenderTargets = 2;
-
- m_desc = desc;
-
- // set viewport
- {
- m_viewport.Width = float(m_desc.width);
- m_viewport.Height = float(m_desc.height);
- m_viewport.MinDepth = 0;
- m_viewport.MaxDepth = 1;
- m_viewport.TopLeftX = 0;
- m_viewport.TopLeftY = 0;
- }
-
- {
- m_scissorRect.left = 0;
- m_scissorRect.top = 0;
- m_scissorRect.right = m_desc.width;
- m_scissorRect.bottom = m_desc.height;
- }
-
- // Describe and create the command queue.
- D3D12_COMMAND_QUEUE_DESC queueDesc = {};
- queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
- queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
-
- SLANG_RETURN_ON_FAIL(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(m_commandQueue.writeRef())));
-
- // Describe the swap chain.
- DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
- swapChainDesc.BufferCount = m_numRenderTargets;
- swapChainDesc.BufferDesc.Width = m_desc.width;
- swapChainDesc.BufferDesc.Height = m_desc.height;
- swapChainDesc.BufferDesc.Format = m_targetFormat;
- swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
- swapChainDesc.OutputWindow = m_hwnd;
- swapChainDesc.SampleDesc.Count = 1;
- swapChainDesc.Windowed = TRUE;
-
- if (m_isFullSpeed)
- {
- m_hasVsync = false;
- m_allowFullScreen = false;
- }
-
- if (!m_hasVsync)
- {
- swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
- }
-
- // Swap chain needs the queue so that it can force a flush on it.
- ComPtr<IDXGISwapChain> swapChain;
- SLANG_RETURN_ON_FAIL(dxgiFactory->CreateSwapChain(m_commandQueue, &swapChainDesc, swapChain.writeRef()));
- SLANG_RETURN_ON_FAIL(swapChain->QueryInterface(m_swapChain.writeRef()));
-
- if (!m_hasVsync)
- {
- m_swapChainWaitableObject = m_swapChain->GetFrameLatencyWaitableObject();
-
- int maxLatency = m_numRenderTargets - 2;
-
- // Make sure the maximum latency is in the range required by dx12 runtime
- maxLatency = (maxLatency < 1) ? 1 : maxLatency;
- maxLatency = (maxLatency > DXGI_MAX_SWAP_CHAIN_BUFFERS) ? DXGI_MAX_SWAP_CHAIN_BUFFERS : maxLatency;
-
- m_swapChain->SetMaximumFrameLatency(maxLatency);
- }
-
- // This sample does not support fullscreen transitions.
- SLANG_RETURN_ON_FAIL(dxgiFactory->MakeWindowAssociation(m_hwnd, DXGI_MWA_NO_ALT_ENTER));
-
- m_renderTargetIndex = m_swapChain->GetCurrentBackBufferIndex();
-
- // Create descriptor heaps.
- {
- // Describe and create a render target view (RTV) descriptor heap.
- D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
-
- rtvHeapDesc.NumDescriptors = m_numRenderTargets;
- rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
- rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
- SLANG_RETURN_ON_FAIL(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(m_rtvHeap.writeRef())));
- m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
- }
-
- {
- // Describe and create a depth stencil view (DSV) descriptor heap.
- D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {};
- dsvHeapDesc.NumDescriptors = 1;
- dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
- dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
- SLANG_RETURN_ON_FAIL(m_device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(m_dsvHeap.writeRef())));
-
- m_dsvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
- }
-
- // Setup frame resources
- {
- SLANG_RETURN_ON_FAIL(createFrameResources());
- }
-
- // Setup fence, and close the command list (as default state without begin/endRender is closed)
- {
- SLANG_RETURN_ON_FAIL(m_fence.init(m_device));
- // Create the command list. When command lists are created they are open, so close it.
- FrameInfo& frame = m_frameInfos[m_frameIndex];
- SLANG_RETURN_ON_FAIL(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, frame.m_commandAllocator, nullptr, IID_PPV_ARGS(m_commandList.writeRef())));
- m_commandList->Close();
- }
-
- {
- D3D12CircularResourceHeap::Desc desc;
- desc.init();
- // Define size
- desc.m_blockSize = 65536;
- // Set up the heap
- m_circularResourceHeap.init(m_device, desc, &m_fence);
- }
-
- // Setup for rendering
- beginRender();
-
- m_isInitialized = true;
- return SLANG_OK;
-}
-
-Result D3D12Renderer::createFrameResources()
-{
- // Create back buffers
- {
- D3D12_CPU_DESCRIPTOR_HANDLE rtvStart(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
-
- // Work out target format
- D3D12_RESOURCE_DESC resourceDesc;
- {
- ComPtr<ID3D12Resource> backBuffer;
- SLANG_RETURN_ON_FAIL(m_swapChain->GetBuffer(0, IID_PPV_ARGS(backBuffer.writeRef())));
- resourceDesc = backBuffer->GetDesc();
- }
- const DXGI_FORMAT resourceFormat = D3DUtil::calcResourceFormat(D3DUtil::USAGE_TARGET, m_targetUsageFlags, resourceDesc.Format);
- const DXGI_FORMAT targetFormat = D3DUtil::calcFormat(D3DUtil::USAGE_TARGET, resourceFormat);
-
- // Set the target format
- m_targetFormat = targetFormat;
-
- // Create a RTV, and a command allocator for each frame.
- for (int i = 0; i < m_numRenderTargets; i++)
- {
- // Get the back buffer
- ComPtr<ID3D12Resource> backBuffer;
- SLANG_RETURN_ON_FAIL(m_swapChain->GetBuffer(UINT(i), IID_PPV_ARGS(backBuffer.writeRef())));
-
- // Set up resource for back buffer
- m_backBufferResources[i].setResource(backBuffer, D3D12_RESOURCE_STATE_COMMON);
- m_backBuffers[i] = &m_backBufferResources[i];
- // Assume they are the same thing for now...
- m_renderTargets[i] = &m_backBufferResources[i];
-
- // If we are multi-sampling - create a render target separate from the back buffer
- if (m_isMultiSampled)
- {
- D3D12_HEAP_PROPERTIES heapProps;
- heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
- D3D12_CLEAR_VALUE clearValue = {};
- clearValue.Format = m_targetFormat;
-
- // Don't know targets alignment, so just memory copy
- ::memcpy(clearValue.Color, m_clearColor, sizeof(m_clearColor));
-
- D3D12_RESOURCE_DESC desc(resourceDesc);
-
- desc.Format = resourceFormat;
- desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
- desc.SampleDesc.Count = m_numTargetSamples;
- desc.SampleDesc.Quality = m_targetSampleQuality;
- desc.Alignment = 0;
-
- SLANG_RETURN_ON_FAIL(m_renderTargetResources[i].initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, desc, D3D12_RESOURCE_STATE_RENDER_TARGET, &clearValue));
- m_renderTargets[i] = &m_renderTargetResources[i];
- }
-
- D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = { rtvStart.ptr + i * m_rtvDescriptorSize };
- m_device->CreateRenderTargetView(*m_renderTargets[i], nullptr, rtvHandle);
- }
- }
-
- // Set up frames
- for (int i = 0; i < m_numRenderFrames; i++)
- {
- FrameInfo& frame = m_frameInfos[i];
- SLANG_RETURN_ON_FAIL(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(frame.m_commandAllocator.writeRef())));
- }
-
- {
- D3D12_RESOURCE_DESC desc = m_backBuffers[0]->getResource()->GetDesc();
- assert(desc.Width == UINT64(m_desc.width) && desc.Height == UINT64(m_desc.height));
- }
-
- // Create the depth stencil view.
- {
- D3D12_HEAP_PROPERTIES heapProps;
- heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
-
- DXGI_FORMAT resourceFormat = D3DUtil::calcResourceFormat(D3DUtil::USAGE_DEPTH_STENCIL, m_depthStencilUsageFlags, m_depthStencilFormat);
- DXGI_FORMAT depthStencilFormat = D3DUtil::calcFormat(D3DUtil::USAGE_DEPTH_STENCIL, resourceFormat);
-
- // Set the depth stencil format
- m_depthStencilFormat = depthStencilFormat;
-
- // Setup default clear
- D3D12_CLEAR_VALUE clearValue = {};
- clearValue.Format = depthStencilFormat;
- clearValue.DepthStencil.Depth = 1.0f;
- clearValue.DepthStencil.Stencil = 0;
-
- D3D12_RESOURCE_DESC resourceDesc = {};
- resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
- resourceDesc.Format = resourceFormat;
- resourceDesc.Width = m_desc.width;
- resourceDesc.Height = m_desc.height;
- resourceDesc.DepthOrArraySize = 1;
- resourceDesc.MipLevels = 1;
- resourceDesc.SampleDesc.Count = m_numTargetSamples;
- resourceDesc.SampleDesc.Quality = m_targetSampleQuality;
- resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
- resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
- resourceDesc.Alignment = 0;
-
- SLANG_RETURN_ON_FAIL(m_depthStencil.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, resourceDesc, D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue));
-
- // Set the depth stencil
- D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilDesc = {};
- depthStencilDesc.Format = depthStencilFormat;
- depthStencilDesc.ViewDimension = m_isMultiSampled ? D3D12_DSV_DIMENSION_TEXTURE2DMS : D3D12_DSV_DIMENSION_TEXTURE2D;
- depthStencilDesc.Flags = D3D12_DSV_FLAG_NONE;
-
- // Set up as the depth stencil view
- m_device->CreateDepthStencilView(m_depthStencil, &depthStencilDesc, m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
- m_depthStencilView = m_dsvHeap->GetCPUDescriptorHandleForHeapStart();
- }
-
- m_viewport.Width = static_cast<float>(m_desc.width);
- m_viewport.Height = static_cast<float>(m_desc.height);
- m_viewport.MaxDepth = 1.0f;
-
- m_scissorRect.right = static_cast<LONG>(m_desc.width);
- m_scissorRect.bottom = static_cast<LONG>(m_desc.height);
-
- return SLANG_OK;
-}
-
-void D3D12Renderer::setClearColor(const float color[4])
-{
- memcpy(m_clearColor, color, sizeof(m_clearColor));
-}
-
-void D3D12Renderer::clearFrame()
-{
- // Record commands
- D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = { m_rtvHeap->GetCPUDescriptorHandleForHeapStart().ptr + m_renderTargetIndex * m_rtvDescriptorSize };
- m_commandList->ClearRenderTargetView(rtvHandle, m_clearColor, 0, nullptr);
- if (m_depthStencil)
- {
- m_commandList->ClearDepthStencilView(m_depthStencilView, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
- }
-}
-
-void D3D12Renderer::presentFrame()
-{
- endRender();
-
- if (m_swapChainWaitableObject)
- {
- // check if now is good time to present
- // This doesn't wait - because the wait time is 0. If it returns WAIT_TIMEOUT it means that no frame is waiting to be be displayed
- // so there is no point doing a present.
- const bool shouldPresent = (WaitForSingleObjectEx(m_swapChainWaitableObject, 0, TRUE) != WAIT_TIMEOUT);
- if (shouldPresent)
- {
- m_swapChain->Present(0, 0);
- }
- }
- else
- {
- if (SLANG_FAILED(m_swapChain->Present(1, 0)))
- {
- assert(!"Problem presenting");
- beginRender();
- return;
- }
- }
-
- // Increment the fence value. Save on the frame - we'll know that frame is done when the fence value >=
- m_frameInfos[m_frameIndex].m_fenceValue = m_fence.nextSignal(m_commandQueue);
-
- // increment frame index after signal
- m_frameIndex = (m_frameIndex + 1) % m_numRenderFrames;
- // Update the render target index.
- m_renderTargetIndex = m_swapChain->GetCurrentBackBufferIndex();
-
- // On the current frame wait until it is completed
- {
- FrameInfo& frame = m_frameInfos[m_frameIndex];
- // If the next frame is not ready to be rendered yet, wait until it is ready.
- m_fence.waitUntilCompleted(frame.m_fenceValue);
- }
-
- // Setup such that rendering can restart
- beginRender();
-}
-
-SlangResult D3D12Renderer::captureScreenSurface(Surface& surfaceOut)
-{
- return captureTextureToSurface(*m_renderTargets[m_renderTargetIndex], surfaceOut);
-}
-
-static D3D12_RESOURCE_STATES _calcResourceState(Resource::Usage usage)
-{
- typedef Resource::Usage Usage;
- switch (usage)
- {
- case Usage::VertexBuffer: return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
- case Usage::IndexBuffer: return D3D12_RESOURCE_STATE_INDEX_BUFFER;
- case Usage::ConstantBuffer: return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
- case Usage::StreamOutput: return D3D12_RESOURCE_STATE_STREAM_OUT;
- case Usage::RenderTarget: return D3D12_RESOURCE_STATE_RENDER_TARGET;
- case Usage::DepthWrite: return D3D12_RESOURCE_STATE_DEPTH_WRITE;
- case Usage::DepthRead: return D3D12_RESOURCE_STATE_DEPTH_READ;
- case Usage::UnorderedAccess: return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
- case Usage::PixelShaderResource: return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
- case Usage::NonPixelShaderResource: return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
- case Usage::GenericRead: return D3D12_RESOURCE_STATE_GENERIC_READ;
- default: return D3D12_RESOURCE_STATES(0);
- }
-}
-
-static D3D12_RESOURCE_FLAGS _calcResourceFlag(Resource::BindFlag::Enum bindFlag)
-{
- typedef Resource::BindFlag BindFlag;
- switch (bindFlag)
- {
- case BindFlag::RenderTarget: return D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
- case BindFlag::DepthStencil: return D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
- case BindFlag::UnorderedAccess: return D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
- default: return D3D12_RESOURCE_FLAG_NONE;
- }
-}
-
-static D3D12_RESOURCE_FLAGS _calcResourceBindFlags(Resource::Usage initialUsage, int bindFlags)
-{
- int dstFlags = 0;
- while (bindFlags)
- {
- int lsb = bindFlags & -bindFlags;
-
- dstFlags |= _calcResourceFlag(Resource::BindFlag::Enum(lsb));
- bindFlags &= ~lsb;
- }
- return D3D12_RESOURCE_FLAGS(dstFlags);
-}
-
-static D3D12_RESOURCE_DIMENSION _calcResourceDimension(Resource::Type type)
-{
- switch (type)
- {
- case Resource::Type::Buffer: return D3D12_RESOURCE_DIMENSION_BUFFER;
- case Resource::Type::Texture1D: return D3D12_RESOURCE_DIMENSION_TEXTURE1D;
- case Resource::Type::TextureCube:
- case Resource::Type::Texture2D:
- {
- return D3D12_RESOURCE_DIMENSION_TEXTURE2D;
- }
- case Resource::Type::Texture3D: return D3D12_RESOURCE_DIMENSION_TEXTURE3D;
- default: return D3D12_RESOURCE_DIMENSION_UNKNOWN;
- }
-}
-
-TextureResource* D3D12Renderer::createTextureResource(Resource::Usage initialUsage, const TextureResource::Desc& descIn, const TextureResource::Data* initData)
-{
- // Description of uploading on Dx12
- // https://msdn.microsoft.com/en-us/library/windows/desktop/dn899215%28v=vs.85%29.aspx
-
- TextureResource::Desc srcDesc(descIn);
- srcDesc.setDefaults(initialUsage);
-
- const DXGI_FORMAT pixelFormat = D3DUtil::getMapFormat(srcDesc.format);
- if (pixelFormat == DXGI_FORMAT_UNKNOWN)
- {
- return nullptr;
- }
-
- const int arraySize = srcDesc.calcEffectiveArraySize();
-
- const D3D12_RESOURCE_DIMENSION dimension = _calcResourceDimension(srcDesc.type);
- if (dimension == D3D12_RESOURCE_DIMENSION_UNKNOWN)
- {
- return nullptr;
- }
-
- const int numMipMaps = srcDesc.numMipLevels;
-
- // Setup desc
- D3D12_RESOURCE_DESC resourceDesc;
-
- resourceDesc.Dimension = dimension;
- resourceDesc.Format = pixelFormat;
- resourceDesc.Width = srcDesc.size.width;
- resourceDesc.Height = srcDesc.size.height;
- resourceDesc.DepthOrArraySize = (srcDesc.size.depth > 1) ? srcDesc.size.depth : arraySize;
-
- resourceDesc.MipLevels = numMipMaps;
- resourceDesc.SampleDesc.Count = srcDesc.sampleDesc.numSamples;
- resourceDesc.SampleDesc.Quality = srcDesc.sampleDesc.quality;
-
- resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
- resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
- resourceDesc.Alignment = 0;
-
- RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(srcDesc));
-
- // Create the target resource
- {
- D3D12_HEAP_PROPERTIES heapProps;
-
- heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
-
- SLANG_RETURN_NULL_ON_FAIL(texture->m_resource.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr));
-
- texture->m_resource.setDebugName(L"Texture");
- }
-
- // Calculate the layout
- List<D3D12_PLACED_SUBRESOURCE_FOOTPRINT> layouts;
- layouts.SetSize(numMipMaps);
- List<UInt64> mipRowSizeInBytes;
- mipRowSizeInBytes.SetSize(numMipMaps);
- List<UInt32> mipNumRows;
- mipNumRows.SetSize(numMipMaps);
-
- // Since textures are effectively immutable currently initData must be set
- assert(initData);
- // We should have this many sub resources
- assert(initData->numSubResources == numMipMaps * srcDesc.size.depth * arraySize);
-
- // This is just the size for one array upload -> not for the whole texure
- UInt64 requiredSize = 0;
- m_device->GetCopyableFootprints(&resourceDesc, 0, numMipMaps, 0, layouts.begin(), mipNumRows.begin(), mipRowSizeInBytes.begin(), &requiredSize);
-
- // Sub resource indexing
- // https://msdn.microsoft.com/en-us/library/windows/desktop/dn705766(v=vs.85).aspx#subresource_indexing
-
- int subResourceIndex = 0;
- for (int i = 0; i < arraySize; i++)
- {
- // Create the upload texture
- D3D12Resource uploadTexture;
- {
- D3D12_HEAP_PROPERTIES heapProps;
-
- heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
-
- D3D12_RESOURCE_DESC uploadResourceDesc;
-
- uploadResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
- uploadResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
- uploadResourceDesc.Width = requiredSize;
- uploadResourceDesc.Height = 1;
- uploadResourceDesc.DepthOrArraySize = 1;
- uploadResourceDesc.MipLevels = 1;
- uploadResourceDesc.SampleDesc.Count = 1;
- uploadResourceDesc.SampleDesc.Quality = 0;
- uploadResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
- uploadResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
- uploadResourceDesc.Alignment = 0;
-
- SLANG_RETURN_NULL_ON_FAIL(uploadTexture.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, uploadResourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr));
-
- uploadTexture.setDebugName(L"TextureUpload");
- }
-
- ID3D12Resource* uploadResource = uploadTexture;
-
- uint8_t* p;
- uploadResource->Map(0, nullptr, reinterpret_cast<void**>(&p));
-
- for (int j = 0; j < numMipMaps; ++j)
- {
- const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& layout = layouts[j];
- const D3D12_SUBRESOURCE_FOOTPRINT& footprint = layout.Footprint;
-
- const TextureResource::Size mipSize = srcDesc.size.calcMipSize(j);
-
- assert(footprint.Width == mipSize.width && footprint.Height == mipSize.height && footprint.Depth == mipSize.depth);
-
- const ptrdiff_t dstMipRowPitch = ptrdiff_t(layouts[j].Footprint.RowPitch);
- const ptrdiff_t srcMipRowPitch = ptrdiff_t(initData->mipRowStrides[j]);
-
- assert(dstMipRowPitch >= srcMipRowPitch);
-
- const uint8_t* srcRow = (const uint8_t*)initData->subResources[subResourceIndex];
- uint8_t* dstRow = p + layouts[j].Offset;
-
- // Copy the depth each mip
- for (int l = 0; l < mipSize.depth; l++)
- {
- // Copy rows
- for (int k = 0; k < mipSize.height; ++k)
- {
- ::memcpy(dstRow, srcRow, srcMipRowPitch);
-
- srcRow += srcMipRowPitch;
- dstRow += dstMipRowPitch;
- }
- }
-
- //assert(srcRow == (const uint8_t*)(srcMip.Buffer() + srcMip.Count()));
- }
- uploadResource->Unmap(0, nullptr);
-
- for (int mipIndex = 0; mipIndex < numMipMaps; ++mipIndex)
- {
- // https://msdn.microsoft.com/en-us/library/windows/desktop/dn903862(v=vs.85).aspx
-
- D3D12_TEXTURE_COPY_LOCATION src;
- src.pResource = uploadTexture;
- src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
- src.PlacedFootprint = layouts[mipIndex];
-
- D3D12_TEXTURE_COPY_LOCATION dst;
- dst.pResource = texture->m_resource;
- dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
- dst.SubresourceIndex = subResourceIndex;
- m_commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
-
- subResourceIndex++;
- }
-
- {
- // const D3D12_RESOURCE_STATES finalState = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
- const D3D12_RESOURCE_STATES finalState = _calcResourceState(initialUsage);
-
- D3D12BarrierSubmitter submitter(m_commandList);
- texture->m_resource.transition(finalState, submitter);
- }
-
- // Block - waiting for copy to complete (so can drop upload texture)
- submitGpuWorkAndWait();
- }
-
- return texture.detach();
-}
-
-BufferResource* D3D12Renderer::createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData)
-{
- typedef BufferResourceImpl::BackingStyle Style;
-
- BufferResource::Desc srcDesc(descIn);
- srcDesc.setDefaults(initialUsage);
-
- RefPtr<BufferResourceImpl> buffer(new BufferResourceImpl(initialUsage, srcDesc));
-
- // Save the style
- buffer->m_backingStyle = BufferResourceImpl::_calcResourceBackingStyle(initialUsage);
-
- D3D12_RESOURCE_DESC bufferDesc;
- _initBufferResourceDesc(srcDesc.sizeInBytes, bufferDesc);
-
- bufferDesc.Flags = _calcResourceBindFlags(initialUsage, srcDesc.bindFlags);
-
- switch (buffer->m_backingStyle)
- {
- case Style::MemoryBacked:
- {
- // Assume the constant buffer will change every frame. We'll just keep a copy of the contents
- // in regular memory until it needed
- buffer->m_memory.SetSize(UInt(srcDesc.sizeInBytes));
- // Initialize
- if (initData)
- {
- ::memcpy(buffer->m_memory.Buffer(), initData, srcDesc.sizeInBytes);
- }
- break;
- }
- case Style::ResourceBacked:
- {
- const D3D12_RESOURCE_STATES initialState = _calcResourceState(initialUsage);
- SLANG_RETURN_NULL_ON_FAIL(createBuffer(bufferDesc, initData, buffer->m_uploadResource, initialState, buffer->m_resource));
- break;
- }
- default: return nullptr;
- }
-
- return buffer.detach();
-}
-
-InputLayout* D3D12Renderer::createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount)
-{
- RefPtr<InputLayoutImpl> layout(new InputLayoutImpl);
-
- // Work out a buffer size to hold all text
- size_t textSize = 0;
- for (int i = 0; i < Int(inputElementCount); ++i)
- {
- const char* text = inputElements[i].semanticName;
- textSize += text ? (::strlen(text) + 1) : 0;
- }
- layout->m_text.SetSize(textSize);
- char* textPos = layout->m_text.Buffer();
-
- //
- List<D3D12_INPUT_ELEMENT_DESC>& elements = layout->m_elements;
- elements.SetSize(inputElementCount);
-
-
- for (UInt i = 0; i < inputElementCount; ++i)
- {
- const InputElementDesc& srcEle = inputElements[i];
- D3D12_INPUT_ELEMENT_DESC& dstEle = elements[i];
-
- // Add text to the buffer
- const char* semanticName = srcEle.semanticName;
- if (semanticName)
- {
- const int len = int(::strlen(semanticName));
- ::memcpy(textPos, semanticName, len + 1);
- semanticName = textPos;
- textPos += len + 1;
- }
-
- dstEle.SemanticName = semanticName;
- dstEle.SemanticIndex = (UINT)srcEle.semanticIndex;
- dstEle.Format = D3DUtil::getMapFormat(srcEle.format);
- dstEle.InputSlot = 0;
- dstEle.AlignedByteOffset = (UINT)srcEle.offset;
- dstEle.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
- dstEle.InstanceDataStepRate = 0;
- }
-
- return layout.detach();
-}
-
-void* D3D12Renderer::map(BufferResource* bufferIn, MapFlavor flavor)
-{
- typedef BufferResourceImpl::BackingStyle Style;
-
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(bufferIn);
- buffer->m_mapFlavor = flavor;
-
- const size_t bufferSize = buffer->getDesc().sizeInBytes;
-
- switch (buffer->m_backingStyle)
- {
- case Style::ResourceBacked:
- {
- // We need this in a state so we can upload
- switch (flavor)
- {
- case MapFlavor::HostWrite:
- case MapFlavor::WriteDiscard:
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- buffer->m_uploadResource.transition(D3D12_RESOURCE_STATE_GENERIC_READ, submitter);
- buffer->m_resource.transition(D3D12_RESOURCE_STATE_COPY_DEST, submitter);
-
- const D3D12_RANGE readRange = {};
-
- void* uploadData;
- SLANG_RETURN_NULL_ON_FAIL(buffer->m_uploadResource.getResource()->Map(0, &readRange, reinterpret_cast<void**>(&uploadData)));
- return uploadData;
-
- break;
- }
- case MapFlavor::HostRead:
- {
- // This will be slow!!! - it blocks CPU on GPU completion
- D3D12Resource& resource = buffer->m_resource;
-
- // Readback heap
- D3D12_HEAP_PROPERTIES heapProps;
- heapProps.Type = D3D12_HEAP_TYPE_READBACK;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
-
- // Resource to readback to
- D3D12_RESOURCE_DESC stagingDesc;
- _initBufferResourceDesc(bufferSize, stagingDesc);
-
- D3D12Resource stageBuf;
- SLANG_RETURN_NULL_ON_FAIL(stageBuf.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, stagingDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr));
-
- const D3D12_RESOURCE_STATES initialState = resource.getState();
-
- // Make it a source
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- resource.transition(D3D12_RESOURCE_STATE_COPY_SOURCE, submitter);
- }
- // Do the copy
- m_commandList->CopyBufferRegion(stageBuf, 0, resource, 0, bufferSize);
- // Switch it back
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- resource.transition(initialState, submitter);
- }
-
- // Wait until complete
- submitGpuWorkAndWait();
-
- // Map and copy
- {
- UINT8* data;
- D3D12_RANGE readRange = { 0, bufferSize };
-
- SLANG_RETURN_NULL_ON_FAIL(stageBuf.getResource()->Map(0, &readRange, reinterpret_cast<void**>(&data)));
-
- // Copy to memory buffer
- buffer->m_memory.SetSize(bufferSize);
- ::memcpy(buffer->m_memory.Buffer(), data, bufferSize);
-
- stageBuf.getResource()->Unmap(0, nullptr);
- }
-
- return buffer->m_memory.Buffer();
- }
- }
- break;
- }
- case Style::MemoryBacked:
- {
- return buffer->m_memory.Buffer();
- }
- default: return nullptr;
- }
-
- return nullptr;
-}
-
-void D3D12Renderer::unmap(BufferResource* bufferIn)
-{
- typedef BufferResourceImpl::BackingStyle Style;
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(bufferIn);
-
- switch (buffer->m_backingStyle)
- {
- case Style::MemoryBacked:
- {
- // Don't need to do anything, as will be uploaded automatically when used
- break;
- }
- case Style::ResourceBacked:
- {
- // We need this in a state so we can upload
- switch (buffer->m_mapFlavor)
- {
- case MapFlavor::HostWrite:
- case MapFlavor::WriteDiscard:
- {
- // Unmap
- ID3D12Resource* uploadResource = buffer->m_uploadResource;
- ID3D12Resource* resource = buffer->m_resource;
-
- uploadResource->Unmap(0, nullptr);
-
- const D3D12_RESOURCE_STATES initialState = buffer->m_resource.getState();
-
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- buffer->m_uploadResource.transition(D3D12_RESOURCE_STATE_GENERIC_READ, submitter);
- buffer->m_resource.transition(D3D12_RESOURCE_STATE_COPY_DEST, submitter);
- }
-
- m_commandList->CopyBufferRegion(resource, 0, uploadResource, 0, buffer->getDesc().sizeInBytes);
-
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- buffer->m_resource.transition(initialState, submitter);
- }
- break;
- }
- case MapFlavor::HostRead:
- {
- break;
- }
- }
- }
- }
-}
-
-void D3D12Renderer::setInputLayout(InputLayout* inputLayout)
-{
- m_boundInputLayout = static_cast<InputLayoutImpl*>(inputLayout);
-}
-
-void D3D12Renderer::setPrimitiveTopology(PrimitiveTopology topology)
-{
- switch (topology)
- {
- case PrimitiveTopology::TriangleList:
- {
- m_primitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
- m_primitiveTopology = D3DUtil::getPrimitiveTopology(topology);
- break;
- }
- default:
- {
- assert(!"Unhandled type");
- }
- }
-}
-
-void D3D12Renderer::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 D3D12Renderer::setShaderProgram(ShaderProgram* inProgram)
-{
- m_boundShaderProgram = static_cast<ShaderProgramImpl*>(inProgram);
-}
-
-void D3D12Renderer::draw(UInt vertexCount, UInt startVertex)
-{
- ID3D12GraphicsCommandList* commandList = m_commandList;
-
- RenderState* renderState = calcRenderState();
- if (!renderState)
- {
- assert(!"Couldn't create render state");
- return;
- }
-
- BindingStateImpl* bindingState = m_boundBindingState;
-
- // Submit - setting for graphics
- {
- GraphicsSubmitter submitter(commandList);
- _bindRenderState(renderState, commandList, &submitter);
- }
-
- commandList->IASetPrimitiveTopology(m_primitiveTopology);
-
- // Set up vertex buffer views
- {
- int numVertexViews = 0;
- D3D12_VERTEX_BUFFER_VIEW vertexViews[16];
- for (int i = 0; i < int(m_boundVertexBuffers.Count()); i++)
- {
- const BoundVertexBuffer& boundVertexBuffer = m_boundVertexBuffers[i];
- BufferResourceImpl* buffer = boundVertexBuffer.m_buffer;
- if (buffer)
- {
- D3D12_VERTEX_BUFFER_VIEW& vertexView = vertexViews[numVertexViews++];
- vertexView.BufferLocation = buffer->m_resource.getResource()->GetGPUVirtualAddress();
- vertexView.SizeInBytes = int(buffer->getDesc().sizeInBytes);
- vertexView.StrideInBytes = boundVertexBuffer.m_stride;
- }
- }
- commandList->IASetVertexBuffers(0, numVertexViews, vertexViews);
- }
-
- commandList->DrawInstanced(UINT(vertexCount), 1, UINT(startVertex), 0);
-}
-
-void D3D12Renderer::dispatchCompute(int x, int y, int z)
-{
- ID3D12GraphicsCommandList* commandList = m_commandList;
- RenderState* renderState = calcRenderState();
-
- // Submit binding for compute
- {
- ComputeSubmitter submitter(commandList);
- _bindRenderState(renderState, commandList, &submitter);
- }
-
- commandList->Dispatch(x, y, z);
-}
-
-BindingState* D3D12Renderer::createBindingState(const BindingState::Desc& bindingStateDesc)
-{
- RefPtr<BindingStateImpl> bindingState(new BindingStateImpl(bindingStateDesc));
-
- SLANG_RETURN_NULL_ON_FAIL(bindingState->init(m_device));
-
- 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)
- {
- const auto& srcEntry = srcBindings[i];
- auto& dstDetail = dstDetails[i];
-
- const int bindingIndex = srcEntry.registerRange.getSingleIndex();
-
- switch (srcEntry.bindingType)
- {
- case BindingType::Buffer:
- {
- assert(srcEntry.resource && srcEntry.resource->isBuffer());
- BufferResourceImpl* bufferResource = static_cast<BufferResourceImpl*>(srcEntry.resource.Ptr());
- const BufferResource::Desc& bufferDesc = bufferResource->getDesc();
-
- const size_t bufferSize = bufferDesc.sizeInBytes;
- const int elemSize = bufferDesc.elementSize <= 0 ? sizeof(uint32_t) : bufferDesc.elementSize;
-
- const bool createSrv = false;
-
- // NOTE! In this arrangement the buffer can either be a ConstantBuffer or a 'StorageBuffer'.
- // If it's a storage buffer then it has a 'uav'.
- // In neither circumstance is there an associated srv
- // This departs a little from dx11 code - in that it will create srv and uav for a storage buffer.
- if (bufferDesc.bindFlags & Resource::BindFlag::UnorderedAccess)
- {
- dstDetail.m_uavIndex = bindingState->m_viewHeap.allocate();
- if (dstDetail.m_uavIndex < 0)
- {
- return nullptr;
- }
-
- D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
-
- uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
- uavDesc.Format = D3DUtil::getMapFormat(bufferDesc.format);
-
- uavDesc.Buffer.StructureByteStride = elemSize;
-
- uavDesc.Buffer.FirstElement = 0;
- uavDesc.Buffer.NumElements = (UINT)(bufferSize / elemSize);
- uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
-
- if (bufferDesc.elementSize == 0 && bufferDesc.format == Format::Unknown)
- {
- uavDesc.Buffer.Flags |= D3D12_BUFFER_UAV_FLAG_RAW;
- uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
-
- uavDesc.Buffer.StructureByteStride = 0;
- }
- else if( bufferDesc.format != Format::Unknown )
- {
- uavDesc.Buffer.StructureByteStride = 0;
- }
-
- m_device->CreateUnorderedAccessView(bufferResource->m_resource, nullptr, &uavDesc, bindingState->m_viewHeap.getCpuHandle(dstDetail.m_uavIndex));
- }
- if (createSrv && (bufferDesc.bindFlags & (Resource::BindFlag::NonPixelShaderResource | Resource::BindFlag::PixelShaderResource)))
- {
- dstDetail.m_srvIndex = bindingState->m_viewHeap.allocate();
- if (dstDetail.m_srvIndex < 0)
- {
- return nullptr;
- }
-
- D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
-
- srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
- srvDesc.Format = DXGI_FORMAT_UNKNOWN;
- srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
-
- srvDesc.Buffer.FirstElement = 0;
- srvDesc.Buffer.NumElements = (UINT)(bufferSize / elemSize);
- srvDesc.Buffer.StructureByteStride = elemSize;
- srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
-
- if (bufferDesc.elementSize == 0)
- {
- srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
- }
-
- m_device->CreateShaderResourceView(bufferResource->m_resource, &srvDesc, bindingState->m_viewHeap.getCpuHandle(dstDetail.m_srvIndex));
- }
-
- break;
- }
- case BindingType::Texture:
- {
- assert(srcEntry.resource && srcEntry.resource->isTexture());
-
- TextureResourceImpl* textureResource = static_cast<TextureResourceImpl*>(srcEntry.resource.Ptr());
-
- dstDetail.m_srvIndex = bindingState->m_viewHeap.allocate();
- if (dstDetail.m_srvIndex < 0)
- {
- return nullptr;
- }
-
- {
- const D3D12_RESOURCE_DESC resourceDesc = textureResource->m_resource.getResource()->GetDesc();
- const DXGI_FORMAT pixelFormat = resourceDesc.Format;
-
- D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
- _initSrvDesc(textureResource->getType(), textureResource->getDesc(), resourceDesc, pixelFormat, srvDesc);
-
- // Create descriptor
- m_device->CreateShaderResourceView(textureResource->m_resource, &srvDesc, bindingState->m_viewHeap.getCpuHandle(dstDetail.m_srvIndex));
- }
-
- break;
- }
- case BindingType::Sampler:
- {
- const BindingState::SamplerDesc& samplerDesc = bindingStateDesc.m_samplerDescs[srcEntry.descIndex];
-
- const int samplerIndex = bindingIndex;
- dstDetail.m_samplerIndex = samplerIndex;
- bindingState->m_samplerHeap.placeAt(samplerIndex);
-
- D3D12_SAMPLER_DESC desc = {};
- desc.AddressU = desc.AddressV = desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
- desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
-
- if (samplerDesc.isCompareSampler)
- {
- desc.ComparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
- desc.Filter = D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT;
- }
- else
- {
- desc.Filter = D3D12_FILTER_ANISOTROPIC;
- desc.MaxAnisotropy = 8;
- desc.MinLOD = 0.0f;
- desc.MaxLOD = 100.0f;
- }
-
- m_device->CreateSampler(&desc, bindingState->m_samplerHeap.getCpuHandle(samplerIndex));
-
- break;
- }
- case BindingType::CombinedTextureSampler:
- {
- assert(!"Not implemented");
- return nullptr;
- }
- }
- }
-
- return bindingState.detach();
-}
-
-void D3D12Renderer::setBindingState(BindingState* state)
-{
- m_boundBindingState = static_cast<BindingStateImpl*>(state);
-}
-
-ShaderProgram* D3D12Renderer::createProgram(const ShaderProgram::Desc& desc)
-{
- RefPtr<ShaderProgramImpl> program(new ShaderProgramImpl());
- program->m_pipelineType = desc.pipelineType;
-
- if (desc.pipelineType == PipelineType::Compute)
- {
- auto computeKernel = desc.findKernel(StageType::Compute);
- program->m_computeShader.InsertRange(0, (const uint8_t*) computeKernel->codeBegin, computeKernel->getCodeSize());
- }
- else
- {
- auto vertexKernel = desc.findKernel(StageType::Vertex);
- auto fragmentKernel = desc.findKernel(StageType::Fragment);
-
- program->m_vertexShader.InsertRange(0, (const uint8_t*) vertexKernel->codeBegin, vertexKernel->getCodeSize());
- program->m_pixelShader.InsertRange(0, (const uint8_t*) fragmentKernel->codeBegin, fragmentKernel->getCodeSize());
- }
-
- return program.detach();
-}
-
-
-} // renderer_test
diff --git a/tools/render-test/render-d3d12.h b/tools/render-test/render-d3d12.h
deleted file mode 100644
index 259af7f7b..000000000
--- a/tools/render-test/render-d3d12.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// render-d3d12.h
-#pragma once
-
-namespace renderer_test {
-
-class Renderer;
-
-Renderer* createD3D12Renderer();
-
-} // renderer_test
diff --git a/tools/render-test/render-gl.cpp b/tools/render-test/render-gl.cpp
deleted file mode 100644
index dc9f0c43a..000000000
--- a/tools/render-test/render-gl.cpp
+++ /dev/null
@@ -1,1049 +0,0 @@
-// render-gl.cpp
-#include "render-gl.h"
-
-#include "options.h"
-#include "render.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "core/basic.h"
-#include "core/secure-crt.h"
-#include "external/stb/stb_image_write.h"
-
-#include "surface.h"
-
-// TODO(tfoley): eventually we should be able to run these
-// tests on non-Windows targets to confirm that cross-compilation
-// at least *works* on those platforms...
-#define WIN32_LEAN_AND_MEAN
-#define NOMINMAX
-#include <Windows.h>
-#undef WIN32_LEAN_AND_MEAN
-#undef NOMINMAX
-
-#ifdef _MSC_VER
-#include <stddef.h>
-#if (_MSC_VER < 1900)
-#define snprintf sprintf_s
-#endif
-#endif
-
-#pragma comment(lib, "opengl32")
-
-#include <GL/GL.h>
-#include "external/glext.h"
-
-// We define an "X-macro" for mapping over loadable OpenGL
-// extension entry point that we will use, so that we can
-// easily write generic code to iterate over them.
-#define MAP_GL_EXTENSION_FUNCS(F) \
- F(glCreateProgram, PFNGLCREATEPROGRAMPROC) \
- F(glCreateShader, PFNGLCREATESHADERPROC) \
- F(glShaderSource, PFNGLSHADERSOURCEPROC) \
- F(glCompileShader, PFNGLCOMPILESHADERPROC) \
- F(glGetShaderiv, PFNGLGETSHADERIVPROC) \
- F(glDeleteShader, PFNGLDELETESHADERPROC) \
- F(glAttachShader, PFNGLATTACHSHADERPROC) \
- F(glLinkProgram, PFNGLLINKPROGRAMPROC) \
- F(glGetProgramiv, PFNGLGETPROGRAMIVPROC) \
- F(glGetProgramInfoLog, PFNGLGETPROGRAMINFOLOGPROC) \
- F(glDeleteProgram, PFNGLDELETEPROGRAMPROC) \
- F(glGetShaderInfoLog, PFNGLGETSHADERINFOLOGPROC) \
- F(glGenBuffers, PFNGLGENBUFFERSPROC) \
- F(glBindBuffer, PFNGLBINDBUFFERPROC) \
- F(glBufferData, PFNGLBUFFERDATAPROC) \
- F(glDeleteBuffers, PFNGLDELETEBUFFERSPROC) \
- F(glMapBuffer, PFNGLMAPBUFFERPROC) \
- F(glUnmapBuffer, PFNGLUNMAPBUFFERPROC) \
- F(glUseProgram, PFNGLUSEPROGRAMPROC) \
- F(glBindBufferBase, PFNGLBINDBUFFERBASEPROC) \
- F(glVertexAttribPointer, PFNGLVERTEXATTRIBPOINTERPROC) \
- F(glEnableVertexAttribArray, PFNGLENABLEVERTEXATTRIBARRAYPROC) \
- F(glDisableVertexAttribArray, PFNGLDISABLEVERTEXATTRIBARRAYPROC) \
- F(glDebugMessageCallback, PFNGLDEBUGMESSAGECALLBACKPROC) \
- F(glDispatchCompute, PFNGLDISPATCHCOMPUTEPROC) \
- F(glActiveTexture, PFNGLACTIVETEXTUREPROC) \
- F(glCreateSamplers, PFNGLCREATESAMPLERSPROC) \
- F(glDeleteSamplers, PFNGLDELETESAMPLERSPROC) \
- F(glBindSampler, PFNGLBINDSAMPLERPROC) \
- F(glTexImage3D, PFNGLTEXIMAGE3DPROC) \
- F(glSamplerParameteri, PFNGLSAMPLERPARAMETERIPROC) \
- /* end */
-
-using namespace Slang;
-
-namespace renderer_test {
-
-class GLRenderer : public Renderer
-{
-public:
-
- // 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& descIn, const void* initData) override;
- virtual SlangResult captureScreenSurface(Surface& surfaceOut) 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::OpenGl; }
-
- protected:
- enum
- {
- kMaxVertexStreams = 16,
- };
-
- struct VertexAttributeFormat
- {
- GLint componentCount;
- GLenum componentType;
- GLboolean normalized;
- };
-
- struct VertexAttributeDesc
- {
- VertexAttributeFormat format;
- GLuint streamIndex;
- GLsizei offset;
- };
-
- class InputLayoutImpl: public InputLayout
- {
- public:
- VertexAttributeDesc m_attributes[kMaxVertexStreams];
- UInt m_attributeCount = 0;
- };
-
- class BufferResourceImpl: public BufferResource
- {
- public:
- typedef BufferResource Parent;
-
- BufferResourceImpl(Usage initialUsage, const Desc& desc, GLRenderer* renderer, GLuint id, GLenum target):
- Parent(desc),
- m_renderer(renderer),
- m_handle(id),
- m_initialUsage(initialUsage),
- m_target(target)
- {}
- ~BufferResourceImpl()
- {
- if (m_renderer)
- {
- m_renderer->glDeleteBuffers(1, &m_handle);
- }
- }
-
- Usage m_initialUsage;
- GLRenderer* m_renderer;
- GLuint m_handle;
- GLenum m_target;
- };
-
- class TextureResourceImpl: public TextureResource
- {
- public:
- typedef TextureResource Parent;
-
- TextureResourceImpl(Usage initialUsage, const Desc& desc, GLRenderer* renderer):
- Parent(desc),
- m_initialUsage(initialUsage),
- m_renderer(renderer)
- {
- m_target = 0;
- m_handle = 0;
- }
-
- ~TextureResourceImpl()
- {
- if (m_handle)
- {
- glDeleteTextures(1, &m_handle);
- }
- }
-
- Usage m_initialUsage;
- GLRenderer* m_renderer;
- GLenum m_target;
- GLuint m_handle;
- };
-
- struct BindingDetail
- {
- GLuint m_samplerHandle = 0;
- };
-
- class BindingStateImpl: public BindingState
- {
- public:
- typedef BindingState Parent;
-
- /// Ctor
- BindingStateImpl(const Desc& desc, GLRenderer* renderer):
- Parent(desc),
- m_renderer(renderer)
- {
- }
-
- ~BindingStateImpl()
- {
- if (m_renderer)
- {
- m_renderer->destroyBindingEntries(getDesc(), m_bindingDetails.Buffer());
- }
- }
-
- GLRenderer* m_renderer;
- List<BindingDetail> m_bindingDetails;
- };
-
- class ShaderProgramImpl : public ShaderProgram
- {
- public:
- ShaderProgramImpl(GLRenderer* renderer, GLuint id):
- m_renderer(renderer),
- m_id(id)
- {
- }
- ~ShaderProgramImpl()
- {
- if (m_renderer)
- {
- m_renderer->glDeleteProgram(m_id);
- }
- }
-
- GLuint m_id;
- GLRenderer* m_renderer;
- };
-
- enum class GlPixelFormat
- {
- Unknown,
- RGBA_Unorm_UInt8,
- CountOf,
- };
-
- struct GlPixelFormatInfo
- {
- GLint internalFormat; // such as GL_RGBA8
- GLenum format; // such as GL_RGBA
- GLenum formatType; // such as GL_UNSIGNED_BYTE
- };
-
- void destroyBindingEntries(const BindingState::Desc& desc, const BindingDetail* details);
-
- void bindBufferImpl(int target, UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets);
- void flushStateForDraw();
- GLuint loadShader(GLenum stage, char const* source);
- void debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message);
-
- /// Returns GlPixelFormat::Unknown if not an equivalent
- static GlPixelFormat _getGlPixelFormat(Format format);
-
- static void APIENTRY staticDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam);
- static VertexAttributeFormat getVertexAttributeFormat(Format format);
-
- static void compileTimeAsserts();
-
- HDC m_hdc;
- HGLRC m_glContext;
- float m_clearColor[4] = { 0, 0, 0, 0 };
-
- RefPtr<ShaderProgramImpl> m_boundShaderProgram;
- RefPtr<InputLayoutImpl> m_boundInputLayout;
-
- GLenum m_boundPrimitiveTopology = GL_TRIANGLES;
- GLuint m_boundVertexStreamBuffers[kMaxVertexStreams];
- UInt m_boundVertexStreamStrides[kMaxVertexStreams];
- UInt m_boundVertexStreamOffsets[kMaxVertexStreams];
-
- Desc m_desc;
-
- // Declare a function pointer for each OpenGL
- // extension function we need to load
-#define DECLARE_GL_EXTENSION_FUNC(NAME, TYPE) TYPE NAME;
- MAP_GL_EXTENSION_FUNCS(DECLARE_GL_EXTENSION_FUNC)
-#undef DECLARE_GL_EXTENSION_FUNC
-
- static const GlPixelFormatInfo s_pixelFormatInfos[]; /// Maps GlPixelFormat to a format info
-};
-
-/* static */GLRenderer::GlPixelFormat GLRenderer::_getGlPixelFormat(Format format)
-{
- switch (format)
- {
- case Format::RGBA_Unorm_UInt8: return GlPixelFormat::RGBA_Unorm_UInt8;
- default: return GlPixelFormat::Unknown;
- }
-}
-
-/* static */ const GLRenderer::GlPixelFormatInfo GLRenderer::s_pixelFormatInfos[] =
-{
- // internalType, format, formatType
- { 0, 0, 0}, // GlPixelFormat::Unknown
- { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE }, // GlPixelFormat::RGBA_Unorm_UInt8
-};
-
-/* static */void GLRenderer::compileTimeAsserts()
-{
- SLANG_COMPILE_TIME_ASSERT(SLANG_COUNT_OF(s_pixelFormatInfos) == int(GlPixelFormat::CountOf));
-}
-
-Renderer* createGLRenderer()
-{
- return new GLRenderer();
-}
-
-void GLRenderer::debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message)
-{
- ::OutputDebugStringA("GL: ");
- ::OutputDebugStringA(message);
- ::OutputDebugStringA("\n");
-
- switch (type)
- {
- case GL_DEBUG_TYPE_ERROR:
- break;
- default:
- break;
- }
-}
-
-/* static */void APIENTRY GLRenderer::staticDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
-{
- ((GLRenderer*)userParam)->debugCallback(source, type, id, severity, length, message);
-}
-
-/* static */GLRenderer::VertexAttributeFormat GLRenderer::getVertexAttributeFormat(Format format)
-{
- switch (format)
- {
- default: assert(!"unexpected"); return VertexAttributeFormat();
-
-#define CASE(NAME, COUNT, TYPE, NORMALIZED) \
- case Format::NAME: do { VertexAttributeFormat result = {COUNT, TYPE, NORMALIZED}; return result; } while (0)
-
- CASE(RGBA_Float32, 4, GL_FLOAT, GL_FALSE);
- CASE(RGB_Float32, 3, GL_FLOAT, GL_FALSE);
- CASE(RG_Float32, 2, GL_FLOAT, GL_FALSE);
- CASE(R_Float32, 1, GL_FLOAT, GL_FALSE);
-#undef CASE
- }
-}
-
-void GLRenderer::bindBufferImpl(int target, UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets)
-{
- for (UInt ii = 0; ii < slotCount; ++ii)
- {
- UInt slot = startSlot + ii;
-
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[ii]);
- GLuint bufferID = buffer ? buffer->m_handle : 0;
-
- assert(!offsets || !offsets[ii]);
-
- glBindBufferBase(target, (GLuint)slot, bufferID);
- }
-}
-
-void GLRenderer::flushStateForDraw()
-{
- auto layout = m_boundInputLayout.Ptr();
- auto attrCount = layout->m_attributeCount;
- for (UInt ii = 0; ii < attrCount; ++ii)
- {
- auto& attr = layout->m_attributes[ii];
-
- auto streamIndex = attr.streamIndex;
-
- glBindBuffer(GL_ARRAY_BUFFER, m_boundVertexStreamBuffers[streamIndex]);
-
- glVertexAttribPointer(
- (GLuint)ii,
- attr.format.componentCount,
- attr.format.componentType,
- attr.format.normalized,
- (GLsizei)m_boundVertexStreamStrides[streamIndex],
- (GLvoid*)(attr.offset + m_boundVertexStreamOffsets[streamIndex]));
-
- glEnableVertexAttribArray((GLuint)ii);
- }
- for (UInt ii = attrCount; ii < kMaxVertexStreams; ++ii)
- {
- glDisableVertexAttribArray((GLuint)ii);
- }
-}
-
-GLuint GLRenderer::loadShader(GLenum stage, const char* source)
-{
- // GLSL is monumentally stupid. It officially requires the `#version` directive
- // to be the first thing in the file, which wouldn't be so bad but the API
- // doesn't provide a way to pass a `#define` into your shader other than by
- // prepending it to the whole thing.
- //
- // We are going to solve this problem by doing some surgery on the source
- // that was passed in.
-
- const char* sourceBegin = source;
- const char* sourceEnd = source + strlen(source);
-
- // Look for a version directive in the user-provided source.
- const char* versionBegin = strstr(source, "#version");
- const char* versionEnd = nullptr;
- if (versionBegin)
- {
- // If we found a directive, then scan for the end-of-line
- // after it, and use that to specify the slice.
- versionEnd = strchr(versionBegin, '\n');
- if (!versionEnd)
- {
- versionEnd = sourceEnd;
- }
- else
- {
- versionEnd = versionEnd + 1;
- }
- }
- else
- {
- // If we didn't find a directive, then treat it as being
- // a zero-byte slice at the start of the string
- versionBegin = sourceBegin;
- versionEnd = sourceBegin;
- }
-
- enum { kMaxSourceStringCount = 16 };
- const GLchar* sourceStrings[kMaxSourceStringCount];
- GLint sourceStringLengths[kMaxSourceStringCount];
-
- int sourceStringCount = 0;
-
- const char* stagePrelude = "\n";
- switch (stage)
- {
-#define CASE(NAME) case GL_##NAME##_SHADER: stagePrelude = "#define __GLSL_" #NAME "__ 1\n"; break
-
- CASE(VERTEX);
- CASE(TESS_CONTROL);
- CASE(TESS_EVALUATION);
- CASE(GEOMETRY);
- CASE(FRAGMENT);
- CASE(COMPUTE);
-
-#undef CASE
- }
-
- const char* prelude =
- "#define __GLSL__ 1\n"
- ;
-
-#define ADD_SOURCE_STRING_SPAN(BEGIN, END) \
- sourceStrings[sourceStringCount] = BEGIN; \
- sourceStringLengths[sourceStringCount++] = GLint(END - BEGIN) \
- /* end */
-
-#define ADD_SOURCE_STRING(BEGIN) \
- sourceStrings[sourceStringCount] = BEGIN; \
- sourceStringLengths[sourceStringCount++] = GLint(strlen(BEGIN)) \
- /* end */
-
- ADD_SOURCE_STRING_SPAN(versionBegin, versionEnd);
- ADD_SOURCE_STRING(stagePrelude);
- ADD_SOURCE_STRING(prelude);
- ADD_SOURCE_STRING_SPAN(sourceBegin, versionBegin);
- ADD_SOURCE_STRING_SPAN(versionEnd, sourceEnd);
-
- auto shaderID = glCreateShader(stage);
- glShaderSource(
- shaderID,
- sourceStringCount,
- &sourceStrings[0],
- &sourceStringLengths[0]);
- glCompileShader(shaderID);
-
- GLint success = GL_FALSE;
- glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
- if (!success)
- {
- int maxSize = 0;
- glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxSize);
-
- auto infoBuffer = (char*)malloc(maxSize);
-
- int infoSize = 0;
- glGetShaderInfoLog(shaderID, maxSize, &infoSize, infoBuffer);
- if (infoSize > 0)
- {
- fprintf(stderr, "%s", infoBuffer);
- ::OutputDebugStringA(infoBuffer);
- }
-
- glDeleteShader(shaderID);
- return 0;
- }
-
- return shaderID;
-}
-
-void GLRenderer::destroyBindingEntries(const BindingState::Desc& desc, const BindingDetail* details)
-{
- const auto& bindings = desc.m_bindings;
- const int numBindings = int(bindings.Count());
- for (int i = 0; i < numBindings; ++i)
- {
- const auto& binding = bindings[i];
- const auto& detail = details[i];
-
- if (binding.bindingType == BindingType::Sampler && detail.m_samplerHandle != 0)
- {
- glDeleteSamplers(1, &detail.m_samplerHandle);
- }
- }
-}
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
-
-SlangResult GLRenderer::initialize(const Desc& desc, void* inWindowHandle)
-{
- auto windowHandle = (HWND)inWindowHandle;
- m_desc = desc;
-
- m_hdc = ::GetDC(windowHandle);
-
- PIXELFORMATDESCRIPTOR pixelFormatDesc = { sizeof(PIXELFORMATDESCRIPTOR) };
- pixelFormatDesc.nVersion = 1;
- pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
- pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
- pixelFormatDesc.cColorBits = 32;
- pixelFormatDesc.cDepthBits = 24;
- pixelFormatDesc.cStencilBits = 8;
- pixelFormatDesc.iLayerType = PFD_MAIN_PLANE;
-
- int pixelFormatIndex = ChoosePixelFormat(m_hdc, &pixelFormatDesc);
- SetPixelFormat(m_hdc, pixelFormatIndex, &pixelFormatDesc);
-
- m_glContext = wglCreateContext(m_hdc);
- wglMakeCurrent(m_hdc, m_glContext);
-
- auto renderer = glGetString(GL_RENDERER);
- auto extensions = glGetString(GL_EXTENSIONS);
-
- // Load each of our extension functions by name
-
-#define LOAD_GL_EXTENSION_FUNC(NAME, TYPE) NAME = (TYPE) wglGetProcAddress(#NAME);
- MAP_GL_EXTENSION_FUNCS(LOAD_GL_EXTENSION_FUNC)
-#undef LOAD_GL_EXTENSION_FUNC
-
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
-
- glViewport(0, 0, desc.width, desc.height);
-
- if (glDebugMessageCallback)
- {
- glEnable(GL_DEBUG_OUTPUT);
- glDebugMessageCallback(staticDebugCallback, this);
- }
-
- return SLANG_OK;
-}
-
-void GLRenderer::setClearColor(const float color[4])
-{
- glClearColor(color[0], color[1], color[2], color[3]);
-}
-
-void GLRenderer::clearFrame()
-{
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-}
-
-void GLRenderer::presentFrame()
-{
- glFlush();
- ::SwapBuffers(m_hdc);
-}
-
-SlangResult GLRenderer::captureScreenSurface(Surface& surfaceOut)
-{
- SLANG_RETURN_ON_FAIL(surfaceOut.allocate(m_desc.width, m_desc.height, Format::RGBA_Unorm_UInt8, 1, SurfaceAllocator::getMallocAllocator()));
- glReadPixels(0, 0, m_desc.width, m_desc.height, GL_RGBA, GL_UNSIGNED_BYTE, surfaceOut.m_data);
- surfaceOut.flipInplaceVertically();
- return SLANG_OK;
-}
-
-TextureResource* GLRenderer::createTextureResource(Resource::Usage initialUsage, const TextureResource::Desc& descIn, const TextureResource::Data* initData)
-{
- TextureResource::Desc srcDesc(descIn);
- srcDesc.setDefaults(initialUsage);
-
- GlPixelFormat pixelFormat = _getGlPixelFormat(srcDesc.format);
- if (pixelFormat == GlPixelFormat::Unknown)
- {
- return nullptr;
- }
-
- const GlPixelFormatInfo& info = s_pixelFormatInfos[int(pixelFormat)];
-
- const GLint internalFormat = info.internalFormat;
- const GLenum format = info.format;
- const GLenum formatType = info.formatType;
-
- RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(initialUsage, srcDesc, this));
-
- GLenum target = 0;
- GLuint handle = 0;
- glGenTextures(1, &handle);
-
- const int effectiveArraySize = srcDesc.calcEffectiveArraySize();
-
- assert(initData);
- assert(initData->numSubResources == srcDesc.numMipLevels * srcDesc.size.depth * effectiveArraySize);
-
- // Set on texture so will be freed if failure
- texture->m_handle = handle;
- const void*const*const data = initData->subResources;
-
- switch (srcDesc.type)
- {
- case Resource::Type::Texture1D:
- {
- if (srcDesc.arraySize > 0)
- {
- target = GL_TEXTURE_1D_ARRAY;
- glBindTexture(target, handle);
-
- int slice = 0;
- for (int i = 0; i < effectiveArraySize; i++)
- {
- for (int j = 0; j < srcDesc.numMipLevels; j++)
- {
- glTexImage2D(target, j, internalFormat, srcDesc.size.width, i, 0, format, formatType, data[slice++]);
- }
- }
- }
- else
- {
- target = GL_TEXTURE_1D;
- glBindTexture(target, handle);
- for (int i = 0; i < srcDesc.numMipLevels; i++)
- {
- glTexImage1D(target, i, internalFormat, srcDesc.size.width, 0, format, formatType, data[i]);
- }
- }
- break;
- }
- case Resource::Type::TextureCube:
- case Resource::Type::Texture2D:
- {
- if (srcDesc.arraySize > 0)
- {
- if (srcDesc.type == Resource::Type::TextureCube)
- {
- target = GL_TEXTURE_CUBE_MAP_ARRAY;
- }
- else
- {
- target = GL_TEXTURE_2D_ARRAY;
- }
-
- glBindTexture(target, handle);
-
- int slice = 0;
- for (int i = 0; i < effectiveArraySize; i++)
- {
- for (int j = 0; j < srcDesc.numMipLevels; j++)
- {
- glTexImage3D(target, j, internalFormat, srcDesc.size.width, srcDesc.size.height, slice, 0, format, formatType, data[slice++]);
- }
- }
- }
- else
- {
- if (srcDesc.type == Resource::Type::TextureCube)
- {
- target = GL_TEXTURE_CUBE_MAP;
- glBindTexture(target, handle);
-
- int slice = 0;
- for (int j = 0; j < 6; j++)
- {
- for (int i = 0; i < srcDesc.numMipLevels; i++)
- {
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i, internalFormat, srcDesc.size.width, srcDesc.size.height, 0, format, formatType, data[slice++]);
- }
- }
- }
- else
- {
- target = GL_TEXTURE_2D;
- glBindTexture(target, handle);
- for (int i = 0; i < srcDesc.numMipLevels; i++)
- {
- glTexImage2D(target, i, internalFormat, srcDesc.size.width, srcDesc.size.height, 0, format, formatType, data[i]);
- }
- }
- }
- break;
- }
- case Resource::Type::Texture3D:
- {
- target = GL_TEXTURE_3D;
- glBindTexture(target, handle);
- for (int i = 0; i < srcDesc.numMipLevels; i++)
- {
- glTexImage3D(target, i, internalFormat, srcDesc.size.width, srcDesc.size.height, srcDesc.size.depth, 0, format, formatType, data[i]);
- }
- break;
- }
- default: return nullptr;
- }
-
- glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
-
- // Assume regular sampling (might be superseded - if a combined sampler wanted)
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f);
-
- texture->m_target = target;
-
- return texture.detach();
-}
-
-static GLenum _calcUsage(Resource::Usage usage)
-{
- typedef Resource::Usage Usage;
- switch (usage)
- {
- case Usage::ConstantBuffer: return GL_DYNAMIC_DRAW;
- default: return GL_STATIC_READ;
- }
-}
-
-static GLenum _calcTarget(Resource::Usage usage)
-{
- typedef Resource::Usage Usage;
- switch (usage)
- {
- case Usage::ConstantBuffer: return GL_UNIFORM_BUFFER;
- default: return GL_SHADER_STORAGE_BUFFER;
- }
-}
-
-BufferResource* GLRenderer::createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData)
-{
- BufferResource::Desc desc(descIn);
- desc.setDefaults(initialUsage);
-
- const GLenum target = _calcTarget(initialUsage);
- // TODO: should derive from desc...
- const GLenum usage = _calcUsage(initialUsage);
-
- GLuint bufferID = 0;
- glGenBuffers(1, &bufferID);
- glBindBuffer(target, bufferID);
-
- glBufferData(target, descIn.sizeInBytes, initData, usage);
-
- return new BufferResourceImpl(initialUsage, desc, this, bufferID, target);
-}
-
-InputLayout* GLRenderer::createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount)
-{
- InputLayoutImpl* inputLayout = new InputLayoutImpl;
-
- inputLayout->m_attributeCount = inputElementCount;
- for (UInt ii = 0; ii < inputElementCount; ++ii)
- {
- auto& inputAttr = inputElements[ii];
- auto& glAttr = inputLayout->m_attributes[ii];
-
- glAttr.streamIndex = 0;
- glAttr.format = getVertexAttributeFormat(inputAttr.format);
- glAttr.offset = (GLsizei)inputAttr.offset;
- }
-
- return (InputLayout*)inputLayout;
-}
-
-void* GLRenderer::map(BufferResource* bufferIn, MapFlavor flavor)
-{
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(bufferIn);
-
- //GLenum target = GL_UNIFORM_BUFFER;
-
- GLuint access = 0;
- switch (flavor)
- {
- case MapFlavor::WriteDiscard:
- case MapFlavor::HostWrite:
- access = GL_WRITE_ONLY;
- break;
- case MapFlavor::HostRead:
- access = GL_READ_ONLY;
- break;
- }
-
- glBindBuffer(buffer->m_target, buffer->m_handle);
-
- return glMapBuffer(buffer->m_target, access);
-}
-
-void GLRenderer::unmap(BufferResource* bufferIn)
-{
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(bufferIn);
- glUnmapBuffer(buffer->m_target);
-}
-
-void GLRenderer::setInputLayout(InputLayout* inputLayout)
-{
- m_boundInputLayout = static_cast<InputLayoutImpl*>(inputLayout);
-}
-
-void GLRenderer::setPrimitiveTopology(PrimitiveTopology topology)
-{
- GLenum glTopology = 0;
- switch (topology)
- {
-#define CASE(NAME, VALUE) case PrimitiveTopology::NAME: glTopology = VALUE; break
-
- CASE(TriangleList, GL_TRIANGLES);
-
-#undef CASE
- }
- m_boundPrimitiveTopology = glTopology;
-}
-
-void GLRenderer::setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets)
-{
- for (UInt ii = 0; ii < slotCount; ++ii)
- {
- UInt slot = startSlot + ii;
-
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[ii]);
- GLuint bufferID = buffer ? buffer->m_handle : 0;
-
- m_boundVertexStreamBuffers[slot] = bufferID;
- m_boundVertexStreamStrides[slot] = strides[ii];
- m_boundVertexStreamOffsets[slot] = offsets[ii];
- }
-}
-
-void GLRenderer::setShaderProgram(ShaderProgram* programIn)
-{
- ShaderProgramImpl* program = static_cast<ShaderProgramImpl*>(programIn);
- m_boundShaderProgram = program;
- GLuint programID = program ? program->m_id : 0;
- glUseProgram(programID);
-}
-
-void GLRenderer::draw(UInt vertexCount, UInt startVertex = 0)
-{
- flushStateForDraw();
-
- glDrawArrays(m_boundPrimitiveTopology, (GLint)startVertex, (GLsizei)vertexCount);
-}
-
-void GLRenderer::dispatchCompute(int x, int y, int z)
-{
- glDispatchCompute(x, y, z);
-}
-
-BindingState* GLRenderer::createBindingState(const BindingState::Desc& bindingStateDesc)
-{
- RefPtr<BindingStateImpl> bindingState(new BindingStateImpl(bindingStateDesc, this));
-
- 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::Texture:
- case BindingType::Buffer:
- {
- break;
- }
- case BindingType::CombinedTextureSampler:
- {
- assert(srcBinding.resource && srcBinding.resource->isTexture());
- TextureResourceImpl* texture = static_cast<TextureResourceImpl*>(srcBinding.resource.Ptr());
- const BindingState::SamplerDesc& samplerDesc = bindingStateDesc.m_samplerDescs[srcBinding.descIndex];
-
- if (samplerDesc.isCompareSampler)
- {
- auto target = texture->m_target;
-
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
- glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- }
- break;
- }
- case BindingType::Sampler:
- {
- const BindingState::SamplerDesc& samplerDesc = bindingStateDesc.m_samplerDescs[srcBinding.descIndex];
-
- GLuint handle;
-
- glCreateSamplers(1, &handle);
- glSamplerParameteri(handle, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glSamplerParameteri(handle, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glSamplerParameteri(handle, GL_TEXTURE_WRAP_R, GL_REPEAT);
-
- if (samplerDesc.isCompareSampler)
- {
- glSamplerParameteri(handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glSamplerParameteri(handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glSamplerParameteri(handle, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
- glSamplerParameteri(handle, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- }
- else
- {
- glSamplerParameteri(handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glSamplerParameteri(handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glSamplerParameteri(handle, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
- }
-
- dstDetail.m_samplerHandle = handle;
- break;
- }
- }
- }
-
- return bindingState.detach();
-}
-
-void GLRenderer::setBindingState(BindingState* stateIn)
-{
- BindingStateImpl* state = static_cast<BindingStateImpl*>(stateIn);
-
- const auto& bindingDesc = state->getDesc();
-
- const auto& details = state->m_bindingDetails;
- const auto& bindings = bindingDesc.m_bindings;
- const int numBindings = int(bindings.Count());
-
- for (int i = 0; i < numBindings; ++i)
- {
- const auto& binding = bindings[i];
- const auto& detail = details[i];
-
- switch (binding.bindingType)
- {
- case BindingType::Buffer:
- {
- const int bindingIndex = binding.registerRange.getSingleIndex();
-
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(binding.resource.Ptr());
- glBindBufferBase(buffer->m_target, bindingIndex, buffer->m_handle);
- break;
- }
- case BindingType::Sampler:
- {
- for (int index = binding.registerRange.index; index < binding.registerRange.index + binding.registerRange.size; ++index)
- {
- glBindSampler(index, detail.m_samplerHandle);
- }
- break;
- }
- case BindingType::Texture:
- case BindingType::CombinedTextureSampler:
- {
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(binding.resource.Ptr());
-
- const int bindingIndex = binding.registerRange.getSingleIndex();
-
- glActiveTexture(GL_TEXTURE0 + bindingIndex);
- glBindTexture(buffer->m_target, buffer->m_handle);
- break;
- }
- }
- }
-}
-
-ShaderProgram* GLRenderer::createProgram(const ShaderProgram::Desc& desc)
-{
- auto programID = glCreateProgram();
- if(desc.pipelineType == PipelineType::Compute )
- {
- auto computeKernel = desc.findKernel(StageType::Compute);
- auto computeShaderID = loadShader(GL_COMPUTE_SHADER, (char const*) computeKernel->codeBegin);
- glAttachShader(programID, computeShaderID);
- glLinkProgram(programID);
- glDeleteShader(computeShaderID);
- }
- else
- {
- auto vertexKernel = desc.findKernel(StageType::Vertex);
- auto fragmentKernel = desc.findKernel(StageType::Fragment);
-
- auto vertexShaderID = loadShader(GL_VERTEX_SHADER, (char const*) vertexKernel->codeBegin);
- auto fragmentShaderID = loadShader(GL_FRAGMENT_SHADER, (char const*) fragmentKernel->codeBegin);
-
- glAttachShader(programID, vertexShaderID);
- glAttachShader(programID, fragmentShaderID);
-
-
- glLinkProgram(programID);
-
- glDeleteShader(vertexShaderID);
- glDeleteShader(fragmentShaderID);
- }
- GLint success = GL_FALSE;
- glGetProgramiv(programID, GL_LINK_STATUS, &success);
- if (!success)
- {
- int maxSize = 0;
- glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &maxSize);
-
- auto infoBuffer = (char*)::malloc(maxSize);
-
- int infoSize = 0;
- glGetProgramInfoLog(programID, maxSize, &infoSize, infoBuffer);
- if (infoSize > 0)
- {
- fprintf(stderr, "%s", infoBuffer);
- OutputDebugStringA(infoBuffer);
- }
-
- ::free(infoBuffer);
-
- glDeleteProgram(programID);
- return nullptr;
- }
-
- return new ShaderProgramImpl(this, programID);
-}
-
-
-} // renderer_test
diff --git a/tools/render-test/render-gl.h b/tools/render-test/render-gl.h
deleted file mode 100644
index 4e6de970c..000000000
--- a/tools/render-test/render-gl.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// render-d3d11.h
-#pragma once
-
-namespace renderer_test {
-
-class Renderer;
-
-Renderer* createGLRenderer();
-
-} // renderer_test
diff --git a/tools/render-test/render-test.vcxproj b/tools/render-test/render-test.vcxproj
index 915d0d753..66ad9e7ed 100644
--- a/tools/render-test/render-test.vcxproj
+++ b/tools/render-test/render-test.vcxproj
@@ -99,7 +99,7 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..\..;..\..\external;..\..\source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\..;..\..\external;..\..\source;..\slang-graphics;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@@ -117,7 +117,7 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..\..;..\..\external;..\..\source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\..;..\..\external;..\..\source;..\slang-graphics;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@@ -135,7 +135,7 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..\..;..\..\external;..\..\source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\..;..\..\external;..\..\source;..\slang-graphics;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
@@ -157,7 +157,7 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..\..;..\..\external;..\..\source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\..;..\..\external;..\..\source;..\slang-graphics;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
@@ -175,50 +175,19 @@
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
- <ClInclude Include="circular-resource-heap-d3d12.h" />
- <ClInclude Include="d3d-util.h" />
- <ClInclude Include="descriptor-heap-d3d12.h" />
<ClInclude Include="options.h" />
<ClInclude Include="png-serialize-util.h" />
- <ClInclude Include="render-d3d11.h" />
- <ClInclude Include="render-d3d12.h" />
- <ClInclude Include="render-gl.h" />
- <ClInclude Include="render-vk.h" />
- <ClInclude Include="render.h" />
- <ClInclude Include="resource-d3d12.h" />
<ClInclude Include="shader-input-layout.h" />
<ClInclude Include="shader-renderer-util.h" />
<ClInclude Include="slang-support.h" />
- <ClInclude Include="surface.h" />
- <ClInclude Include="vk-api.h" />
- <ClInclude Include="vk-device-queue.h" />
- <ClInclude Include="vk-module.h" />
- <ClInclude Include="vk-swap-chain.h" />
- <ClInclude Include="vk-util.h" />
- <ClInclude Include="window.h" />
</ItemGroup>
<ItemGroup>
- <ClCompile Include="circular-resource-heap-d3d12.cpp" />
- <ClCompile Include="d3d-util.cpp" />
- <ClCompile Include="descriptor-heap-d3d12.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="options.cpp" />
<ClCompile Include="png-serialize-util.cpp" />
- <ClCompile Include="render-d3d11.cpp" />
- <ClCompile Include="render-d3d12.cpp" />
- <ClCompile Include="render-gl.cpp" />
- <ClCompile Include="render-vk.cpp" />
- <ClCompile Include="render.cpp" />
- <ClCompile Include="resource-d3d12.cpp" />
<ClCompile Include="shader-input-layout.cpp" />
<ClCompile Include="shader-renderer-util.cpp" />
<ClCompile Include="slang-support.cpp" />
- <ClCompile Include="surface.cpp" />
- <ClCompile Include="vk-api.cpp" />
- <ClCompile Include="vk-device-queue.cpp" />
- <ClCompile Include="vk-module.cpp" />
- <ClCompile Include="vk-swap-chain.cpp" />
- <ClCompile Include="vk-util.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\source\core\core.vcxproj">
@@ -227,6 +196,9 @@
<ProjectReference Include="..\..\source\slang\slang.vcxproj">
<Project>{DB00DA62-0533-4AFD-B59F-A67D5B3A0808}</Project>
</ProjectReference>
+ <ProjectReference Include="..\slang-graphics\slang-graphics.vcxproj">
+ <Project>{222F7498-B40C-4F3F-A704-DDEB91A4484A}</Project>
+ </ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/tools/render-test/render-test.vcxproj.filters b/tools/render-test/render-test.vcxproj.filters
index b2f48a397..ff3d52a7e 100644
--- a/tools/render-test/render-test.vcxproj.filters
+++ b/tools/render-test/render-test.vcxproj.filters
@@ -9,39 +9,12 @@
</Filter>
</ItemGroup>
<ItemGroup>
- <ClInclude Include="circular-resource-heap-d3d12.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="d3d-util.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="descriptor-heap-d3d12.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="options.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="png-serialize-util.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="render-d3d11.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="render-d3d12.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="render-gl.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="render-vk.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="render.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="resource-d3d12.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="shader-input-layout.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -51,38 +24,8 @@
<ClInclude Include="slang-support.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="surface.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="vk-api.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="vk-device-queue.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="vk-module.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="vk-swap-chain.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="vk-util.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="window.h">
- <Filter>Header Files</Filter>
- </ClInclude>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="circular-resource-heap-d3d12.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="d3d-util.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="descriptor-heap-d3d12.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -92,24 +35,6 @@
<ClCompile Include="png-serialize-util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="render-d3d11.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="render-d3d12.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="render-gl.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="render-vk.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="render.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="resource-d3d12.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="shader-input-layout.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -119,23 +44,5 @@
<ClCompile Include="slang-support.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="surface.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="vk-api.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="vk-device-queue.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="vk-module.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="vk-swap-chain.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="vk-util.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
</ItemGroup>
</Project> \ No newline at end of file
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
diff --git a/tools/render-test/render-vk.h b/tools/render-test/render-vk.h
deleted file mode 100644
index 7f6d789d0..000000000
--- a/tools/render-test/render-vk.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// render-vk.h
-#pragma once
-
-namespace renderer_test {
-
-class Renderer;
-
-Renderer* createVKRenderer();
-
-} // renderer_test
diff --git a/tools/render-test/render.cpp b/tools/render-test/render.cpp
deleted file mode 100644
index bfb7aeb94..000000000
--- a/tools/render-test/render.cpp
+++ /dev/null
@@ -1,390 +0,0 @@
-// render.cpp
-#include "render.h"
-
-#include "../../source/core/slang-math.h"
-
-namespace renderer_test {
-using namespace Slang;
-
-/* static */const Resource::BindFlag::Enum Resource::s_requiredBinding[] =
-{
- BindFlag::VertexBuffer, // VertexBuffer
- BindFlag::IndexBuffer, // IndexBuffer
- BindFlag::ConstantBuffer, // ConstantBuffer
- BindFlag::StreamOutput, // StreamOut
- BindFlag::RenderTarget, // RenderTager
- BindFlag::DepthStencil, // DepthRead
- BindFlag::DepthStencil, // DepthWrite
- BindFlag::UnorderedAccess, // UnorderedAccess
- BindFlag::PixelShaderResource, // PixelShaderResource
- BindFlag::NonPixelShaderResource, // NonPixelShaderResource
- BindFlag::Enum(BindFlag::PixelShaderResource | BindFlag::NonPixelShaderResource), // GenericRead
-};
-
-
-/* static */void Resource::compileTimeAsserts()
-{
- SLANG_COMPILE_TIME_ASSERT(SLANG_COUNT_OF(s_requiredBinding) == int(Usage::CountOf));
-}
-
-static const Resource::DescBase s_emptyDescBase = {};
-
-const Resource::DescBase& Resource::getDescBase() const
-{
- if (isBuffer())
- {
- return static_cast<const BufferResource *>(this)->getDesc();
- }
- else if (isTexture())
- {
- return static_cast<const TextureResource *>(this)->getDesc();
- }
- return s_emptyDescBase;
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! RendererUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-/* static */const uint8_t RendererUtil::s_formatSize[] =
-{
- 0, // Unknown,
-
- uint8_t(sizeof(float) * 4), // RGBA_Float32,
- uint8_t(sizeof(float) * 3), // RGB_Float32,
- uint8_t(sizeof(float) * 2), // RG_Float32,
- uint8_t(sizeof(float) * 1), // R_Float32,
-
- uint8_t(sizeof(uint32_t)), // RGBA_Unorm_UInt8,
-
- uint8_t(sizeof(uint32_t)), // R_UInt32,
-
- uint8_t(sizeof(float)), // D_Float32,
- uint8_t(sizeof(uint32_t)), // D_Unorm24_S8,
-};
-
-/* static */const BindingStyle RendererUtil::s_rendererTypeToBindingStyle[] =
-{
- BindingStyle::Unknown, // Unknown,
- BindingStyle::DirectX, // DirectX11,
- BindingStyle::DirectX, // DirectX12,
- BindingStyle::OpenGl, // OpenGl,
- BindingStyle::Vulkan, // Vulkan
-};
-
-/* static */void RendererUtil::compileTimeAsserts()
-{
- SLANG_COMPILE_TIME_ASSERT(SLANG_COUNT_OF(s_formatSize) == int(Format::CountOf));
- SLANG_COMPILE_TIME_ASSERT(SLANG_COUNT_OF(s_rendererTypeToBindingStyle) == int(RendererType::CountOf));
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!! BindingState::Desc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-void BindingState::Desc::addSampler(const SamplerDesc& desc, const RegisterRange& registerRange)
-{
- int descIndex = int(m_samplerDescs.Count());
- m_samplerDescs.Add(desc);
-
- Binding binding;
- binding.bindingType = BindingType::Sampler;
- binding.resource = nullptr;
- binding.registerRange = registerRange;
- binding.descIndex = descIndex;
-
- m_bindings.Add(binding);
-}
-
-void BindingState::Desc::addResource(BindingType bindingType, Resource* resource, const RegisterRange& registerRange)
-{
- assert(resource);
-
- Binding binding;
- binding.bindingType = bindingType;
- binding.resource = resource;
- binding.descIndex = -1;
- binding.registerRange = registerRange;
- m_bindings.Add(binding);
-}
-
-void BindingState::Desc::addCombinedTextureSampler(TextureResource* resource, const SamplerDesc& samplerDesc, const RegisterRange& registerRange)
-{
- assert(resource);
-
- int samplerDescIndex = int(m_samplerDescs.Count());
- m_samplerDescs.Add(samplerDesc);
-
- Binding binding;
- binding.bindingType = BindingType::CombinedTextureSampler;
- binding.resource = resource;
- binding.descIndex = samplerDescIndex;
- binding.registerRange = registerRange;
- m_bindings.Add(binding);
-}
-
-void BindingState::Desc::clear()
-{
- m_bindings.Clear();
- m_samplerDescs.Clear();
- m_numRenderTargets = 1;
-}
-
-int BindingState::Desc::findBindingIndex(Resource::BindFlag::Enum bindFlag, int registerIndex) const
-{
- const int numBindings = int(m_bindings.Count());
- for (int i = 0; i < numBindings; ++i)
- {
- const Binding& binding = m_bindings[i];
- if (binding.resource && (binding.resource->getDescBase().bindFlags & bindFlag) != 0)
- {
- if (binding.registerRange.hasRegister(registerIndex))
- {
- return i;
- }
- }
- }
-
- return -1;
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!! TextureResource::Size !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-int TextureResource::Size::calcMaxDimension(Type type) const
-{
- switch (type)
- {
- case Resource::Type::Texture1D: return this->width;
- case Resource::Type::Texture3D: return std::max(std::max(this->width, this->height), this->depth);
- case Resource::Type::TextureCube: // fallthru
- case Resource::Type::Texture2D:
- {
- return std::max(this->width, this->height);
- }
- default: return 0;
- }
-}
-
-TextureResource::Size TextureResource::Size::calcMipSize(int mipLevel) const
-{
- Size size;
- size.width = TextureResource::calcMipSize(this->width, mipLevel);
- size.height = TextureResource::calcMipSize(this->height, mipLevel);
- size.depth = TextureResource::calcMipSize(this->depth, mipLevel);
- return size;
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!! BufferResource::Desc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-void BufferResource::Desc::setDefaults(Usage initialUsage)
-{
- if (this->bindFlags == 0)
- {
- this->bindFlags = Resource::s_requiredBinding[int(initialUsage)];
- }
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!! TextureResource::Desc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-int TextureResource::Desc::calcNumMipLevels() const
-{
- const int maxDimensionSize = this->size.calcMaxDimension(type);
- return (maxDimensionSize > 0) ? (Math::Log2Floor(maxDimensionSize) + 1) : 0;
-}
-
-int TextureResource::Desc::calcNumSubResources() const
-{
- const int numMipMaps = (this->numMipLevels > 0) ? this->numMipLevels : calcNumMipLevels();
- const int arrSize = (this->arraySize > 0) ? this->arraySize : 1;
-
- switch (type)
- {
- case Resource::Type::Texture1D:
- case Resource::Type::Texture2D:
- {
- return numMipMaps * arrSize;
- }
- case Resource::Type::Texture3D:
- {
- // can't have arrays of 3d textures
- assert(this->arraySize <= 1);
- return numMipMaps * this->size.depth;
- }
- case Resource::Type::TextureCube:
- {
- // There are 6 faces to a cubemap
- return numMipMaps * arrSize * 6;
- }
- default: return 0;
- }
-}
-
-void TextureResource::Desc::fixSize()
-{
- switch (type)
- {
- case Resource::Type::Texture1D:
- {
- this->size.height = 1;
- this->size.depth = 1;
- break;
- }
- case Resource::Type::TextureCube:
- case Resource::Type::Texture2D:
- {
- this->size.depth = 1;
- break;
- }
- case Resource::Type::Texture3D:
- {
- // Can't have an array
- this->arraySize = 0;
- break;
- }
- default: break;
- }
-}
-
-void TextureResource::Desc::setDefaults(Usage initialUsage)
-{
- fixSize();
- if (this->bindFlags == 0)
- {
- this->bindFlags = Resource::s_requiredBinding[int(initialUsage)];
- }
- if (this->numMipLevels <= 0)
- {
- this->numMipLevels = calcNumMipLevels();
- }
-}
-
-int TextureResource::Desc::calcEffectiveArraySize() const
-{
- const int arrSize = (this->arraySize > 0) ? this->arraySize : 1;
-
- switch (type)
- {
- case Resource::Type::Texture1D: // fallthru
- case Resource::Type::Texture2D:
- {
- return arrSize;
- }
- case Resource::Type::TextureCube: return arrSize * 6;
- case Resource::Type::Texture3D: return 1;
- default: return 0;
- }
-}
-
-void TextureResource::Desc::init(Type typeIn)
-{
- this->type = typeIn;
- this->size.init();
-
- this->format = Format::Unknown;
- this->arraySize = 0;
- this->numMipLevels = 0;
- this->sampleDesc.init();
-
- this->bindFlags = 0;
- this->cpuAccessFlags = 0;
-}
-
-void TextureResource::Desc::init1D(Format formatIn, int widthIn, int numMipMapsIn)
-{
- this->type = Type::Texture1D;
- this->size.init(widthIn);
-
- this->format = format;
- this->arraySize = 0;
- this->numMipLevels = numMipMapsIn;
- this->sampleDesc.init();
-
- this->bindFlags = 0;
- this->cpuAccessFlags = 0;
-}
-
-void TextureResource::Desc::init2D(Type typeIn, Format formatIn, int widthIn, int heightIn, int numMipMapsIn)
-{
- assert(typeIn == Type::Texture2D || typeIn == Type::TextureCube);
-
- this->type = type;
- this->size.init(widthIn, heightIn);
-
- this->format = format;
- this->arraySize = 0;
- this->numMipLevels = numMipMapsIn;
- this->sampleDesc.init();
-
- this->bindFlags = 0;
- this->cpuAccessFlags = 0;
-}
-
-void TextureResource::Desc::init3D(Format formatIn, int widthIn, int heightIn, int depthIn, int numMipMapsIn)
-{
- this->type = Type::Texture3D;
- this->size.init(widthIn, heightIn, depthIn);
-
- this->format = format;
- this->arraySize = 0;
- this->numMipLevels = numMipMapsIn;
- this->sampleDesc.init();
-
- this->bindFlags = 0;
- this->cpuAccessFlags = 0;
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!! RennderUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-ProjectionStyle RendererUtil::getProjectionStyle(RendererType type)
-{
- switch (type)
- {
- case RendererType::DirectX11:
- case RendererType::DirectX12:
- {
- return ProjectionStyle::DirectX;
- }
- case RendererType::OpenGl: return ProjectionStyle::OpenGl;
- case RendererType::Vulkan: return ProjectionStyle::Vulkan;
- case RendererType::Unknown: return ProjectionStyle::Unknown;
- default:
- {
- assert(!"Unhandled type");
- return ProjectionStyle::Unknown;
- }
- }
-}
-
-/* static */void RendererUtil::getIdentityProjection(ProjectionStyle style, float projMatrix[16])
-{
- switch (style)
- {
- case ProjectionStyle::DirectX:
- case ProjectionStyle::OpenGl:
- {
- static const float kIdentity[] =
- {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1
- };
- ::memcpy(projMatrix, kIdentity, sizeof(kIdentity));
- break;
- }
- case ProjectionStyle::Vulkan:
- {
- static const float kIdentity[] =
- {
- 1, 0, 0, 0,
- 0, -1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1
- };
- ::memcpy(projMatrix, kIdentity, sizeof(kIdentity));
- break;
- }
- default:
- {
- assert(!"Not handled");
- }
- }
-}
-
-} // renderer_test
diff --git a/tools/render-test/render.h b/tools/render-test/render.h
deleted file mode 100644
index 6a3c58a05..000000000
--- a/tools/render-test/render.h
+++ /dev/null
@@ -1,583 +0,0 @@
-// render.h
-#pragma once
-
-#include "window.h"
-
-//#include "shader-input-layout.h"
-
-#include "../../slang-com-helper.h"
-
-#include "../../source/core/smart-pointer.h"
-#include "../../source/core/list.h"
-
-namespace renderer_test {
-
-// Had to move here, because Options needs types defined here
-typedef intptr_t Int;
-typedef uintptr_t UInt;
-
-// pre declare types
-class Surface;
-
-// Declare opaque type
-class InputLayout: public Slang::RefObject
-{
- public:
-};
-
-enum class PipelineType
-{
- Unknown,
- Graphics,
- Compute,
- CountOf,
-};
-
-enum class StageType
-{
- Unknown,
- Vertex,
- Hull,
- Domain,
- Geometry,
- Fragment,
- Compute,
- CountOf,
-};
-
-enum class RendererType
-{
- Unknown,
- DirectX11,
- DirectX12,
- OpenGl,
- Vulkan,
- CountOf,
-};
-
-enum class ProjectionStyle
-{
- Unknown,
- OpenGl,
- DirectX,
- Vulkan,
- CountOf,
-};
-
-/// The style of the binding
-enum class BindingStyle
-{
- Unknown,
- DirectX,
- OpenGl,
- Vulkan,
- CountOf,
-};
-
-class ShaderProgram: public Slang::RefObject
-{
-public:
-
- struct KernelDesc
- {
- StageType stage;
- void const* codeBegin;
- void const* codeEnd;
-
- UInt getCodeSize() const { return (char const*)codeEnd - (char const*)codeBegin; }
- };
-
- struct Desc
- {
- PipelineType pipelineType;
- KernelDesc const* kernels;
- Int kernelCount;
-
- /// Find and return the kernel for `stage`, if present.
- KernelDesc const* findKernel(StageType stage) const
- {
- for(Int ii = 0; ii < kernelCount; ++ii)
- if(kernels[ii].stage == stage)
- return &kernels[ii];
- return nullptr;
- }
- };
-};
-
-struct ShaderCompileRequest
-{
- struct SourceInfo
- {
- char const* path;
-
- // The data may either be source text (in which
- // case it can be assumed to be nul-terminated with
- // `dataEnd` pointing at the terminator), or
- // raw binary data (in which case `dataEnd` points
- // at the end of the buffer).
- char const* dataBegin;
- char const* dataEnd;
- };
-
- struct EntryPoint
- {
- char const* name = nullptr;
- SourceInfo source;
- };
-
- SourceInfo source;
- EntryPoint vertexShader;
- EntryPoint fragmentShader;
- EntryPoint computeShader;
- Slang::List<Slang::String> entryPointTypeArguments;
-};
-
-/// Different formats of things like pixels or elements of vertices
-/// NOTE! Any change to this type (adding, removing, changing order) - must also be reflected in changes to RendererUtil
-enum class Format
-{
- Unknown,
-
- RGBA_Float32,
- RGB_Float32,
- RG_Float32,
- R_Float32,
-
- RGBA_Unorm_UInt8,
-
- R_UInt32,
-
- D_Float32,
- D_Unorm24_S8,
-
- CountOf,
-};
-
-struct InputElementDesc
-{
- char const* semanticName;
- UInt semanticIndex;
- Format format;
- UInt offset;
-};
-
-enum class MapFlavor
-{
- Unknown, ///< Unknown mapping type
- HostRead,
- HostWrite,
- WriteDiscard,
-};
-
-enum class PrimitiveTopology
-{
- TriangleList,
-};
-
-class Resource: public Slang::RefObject
-{
- public:
-
- /// The type of resource.
- /// NOTE! The order needs to be such that all texture types are at or after Texture1D (otherwise isTexture won't work correctly)
- enum class Type
- {
- Unknown, ///< Unknown
- Buffer, ///< A buffer (like a constant/index/vertex buffer)
- Texture1D, ///< A 1d texture
- Texture2D, ///< A 2d texture
- Texture3D, ///< A 3d texture
- TextureCube, ///< A cubemap consists of 6 Texture2D like faces
- CountOf,
- };
-
- /// Describes how a resource is to be used
- enum class Usage
- {
- Unknown = -1,
- VertexBuffer = 0,
- IndexBuffer,
- ConstantBuffer,
- StreamOutput,
- RenderTarget,
- DepthRead,
- DepthWrite,
- UnorderedAccess,
- PixelShaderResource,
- NonPixelShaderResource,
- GenericRead,
- CountOf,
- };
-
- /// Binding flags describe all of the ways a resource can be bound - and therefore used
- struct BindFlag
- {
- enum Enum
- {
- VertexBuffer = 0x001,
- IndexBuffer = 0x002,
- ConstantBuffer = 0x004,
- StreamOutput = 0x008,
- RenderTarget = 0x010,
- DepthStencil = 0x020,
- UnorderedAccess = 0x040,
- PixelShaderResource = 0x080,
- NonPixelShaderResource = 0x100,
- };
- };
-
- /// Combinations describe how a resource can be accessed (typically by the host/cpu)
- struct AccessFlag
- {
- enum Enum
- {
- Read = 0x1,
- Write = 0x2
- };
- };
-
- /// Base class for Descs
- struct DescBase
- {
- bool canBind(BindFlag::Enum bindFlag) const { return (bindFlags & bindFlag) != 0; }
- bool hasCpuAccessFlag(AccessFlag::Enum accessFlag) { return (cpuAccessFlags & accessFlag) != 0; }
-
- Type type = Type::Unknown;
-
- int bindFlags = 0; ///< Combination of Resource::BindFlag or 0 (and will use initialUsage to set)
- int cpuAccessFlags = 0; ///< Combination of Resource::AccessFlag
- };
-
- /// Get the type
- SLANG_FORCE_INLINE Type getType() const { return m_type; }
- /// True if it's a texture derived type
- SLANG_FORCE_INLINE bool isTexture() const { return int(m_type) >= int(Type::Texture1D); }
- /// True if it's a buffer derived type
- SLANG_FORCE_INLINE bool isBuffer() const { return m_type == Type::Buffer; }
-
- /// Get the descBase
- const DescBase& getDescBase() const;
- /// Returns true if can bind with flag
- bool canBind(BindFlag::Enum bindFlag) const { return getDescBase().canBind(bindFlag); }
-
- /// For a usage gives the required binding flags
- static const BindFlag::Enum s_requiredBinding[]; /// Maps Usage to bind flags required
-
- protected:
- Resource(Type type):
- m_type(type)
- {}
-
- static void compileTimeAsserts();
-
- Type m_type;
-};
-
-class BufferResource: public Resource
-{
- public:
- typedef Resource Parent;
-
- struct Desc: public DescBase
- {
- void init(size_t sizeInBytesIn)
- {
- sizeInBytes = sizeInBytesIn;
- elementSize = 0;
- format = Format::Unknown;
- }
- /// Set up default parameters based on usage
- void setDefaults(Usage initialUsage);
-
- size_t sizeInBytes; ///< Total size in bytes
- int elementSize; ///< Get the element stride. If > 0, this is a structured buffer
- Format format;
- };
-
- /// Get the buffer description
- SLANG_FORCE_INLINE const Desc& getDesc() const { return m_desc; }
-
- /// Ctor
- BufferResource(const Desc& desc):
- Parent(Type::Buffer),
- m_desc(desc)
- {
- }
-
- protected:
- Desc m_desc;
-};
-
-class TextureResource: public Resource
-{
- public:
- typedef Resource Parent;
-
- struct SampleDesc
- {
- void init()
- {
- numSamples = 1;
- quality = 0;
- }
- int numSamples; ///< Number of samples per pixel
- int quality; ///< The quality measure for the samples
- };
-
- struct Size
- {
- void init()
- {
- width = height = depth = 1;
- }
- void init(int widthIn, int heightIn = 1, int depthIn = 1)
- {
- width = widthIn;
- height = heightIn;
- depth = depthIn;
- }
- /// Given the type works out the maximum dimension size
- int calcMaxDimension(Type type) const;
- /// Given a size, calculates the size at a mip level
- Size calcMipSize(int mipLevel) const;
-
- int width; ///< Width in pixels
- int height; ///< Height in pixels (if 2d or 3d)
- int depth; ///< Depth (if 3d)
- };
-
- struct Desc: public DescBase
- {
- /// Initialize with default values
- void init(Type typeIn);
- /// Initialize different dimensions. For cubemap, use init2D
- void init1D(Format format, int width, int numMipMaps = 0);
- void init2D(Type typeIn, Format format, int width, int height, int numMipMaps = 0);
- void init3D(Format format, int width, int height, int depth, int numMipMaps = 0);
-
- /// Given the type, calculates the number of mip maps. 0 on error
- int calcNumMipLevels() const;
- /// Calculate the total number of sub resources. 0 on error.
- int calcNumSubResources() const;
-
- /// Calculate the effective array size - in essence the amount if mip map sets needed.
- /// In practice takes into account if the arraySize is 0 (it's not an array, but it will still have at least one mip set)
- /// and if the type is a cubemap (multiplies the amount of mip sets by 6)
- int calcEffectiveArraySize() const;
-
- /// Use type to fix the size values (and array size).
- /// For example a 1d texture, should have height and depth set to 1.
- void fixSize();
-
- /// Set up default parameters based on type and usage
- void setDefaults(Usage initialUsage);
-
- Size size;
-
- int arraySize; ///< Array size
-
- int numMipLevels; ///< Number of mip levels - if 0 will create all mip levels
- Format format; ///< The resources format
- SampleDesc sampleDesc; ///< How the resource is sampled
- };
-
- /// The ordering of the subResources is
- /// forall (effectiveArraySize)
- /// forall (mip levels)
- /// forall (depth levels)
- struct Data
- {
- ptrdiff_t* mipRowStrides; ///< The row stride for a mip map
- int numMips; ///< The number of mip maps
- const void*const* subResources; ///< Pointers to each full mip subResource
- int numSubResources; ///< The total amount of subResources. Typically = numMips * depth * arraySize
- };
-
- /// Get the description of the texture
- SLANG_FORCE_INLINE const Desc& getDesc() const { return m_desc; }
-
- /// Ctor
- TextureResource(const Desc& desc):
- Parent(desc.type),
- m_desc(desc)
- {
- }
-
- SLANG_FORCE_INLINE static int calcMipSize(int width, int mipLevel)
- {
- width = width >> mipLevel;
- return width > 0 ? width : 1;
- }
-
- protected:
- Desc m_desc;
-};
-
-enum class BindingType
-{
- Unknown,
- Sampler,
- Buffer,
- Texture,
- CombinedTextureSampler,
- CountOf,
-};
-
-class BindingState : public Slang::RefObject
-{
-public:
- /// A register set consists of one or more contiguous indices.
- /// To be valid index >= 0 and size >= 1
- struct RegisterRange
- {
- /// True if contains valid contents
- bool isValid() const { return size > 0; }
- /// True if valid single value
- bool isSingle() const { return size == 1; }
- /// Get as a single index (must be at least one index)
- int getSingleIndex() const { return (size == 1) ? index : -1; }
- /// Return the first index
- int getFirstIndex() const { return (size > 0) ? index : -1; }
- /// True if contains register index
- bool hasRegister(int registerIndex) const { return registerIndex >= index && registerIndex < index + size; }
-
- static RegisterRange makeInvalid() { return RegisterRange{ -1, 0 }; }
- static RegisterRange makeSingle(int index) { return RegisterRange{ int16_t(index), 1 }; }
- static RegisterRange makeRange(int index, int size) { return RegisterRange{ int16_t(index), uint16_t(size) }; }
-
- int16_t index; ///< The base index
- uint16_t size; ///< The amount of register indices
- };
-
- struct SamplerDesc
- {
- bool isCompareSampler;
- };
-
- struct Binding
- {
- BindingType bindingType; ///< Type of binding
- int descIndex; ///< The description index associated with type. -1 if not used. For example if bindingType is Sampler, the descIndex is into m_samplerDescs.
- Slang::RefPtr<Resource> resource; ///< Associated resource. nullptr if not used
- RegisterRange registerRange; /// Defines the registers for binding
- };
-
- struct Desc
- {
- /// Add a resource - assumed that the binding will match the Desc of the resource
- void addResource(BindingType bindingType, Resource* resource, const RegisterRange& registerRange);
- /// Add a sampler
- void addSampler(const SamplerDesc& desc, const RegisterRange& registerRange);
- /// Add a BufferResource
- void addBufferResource(BufferResource* resource, const RegisterRange& registerRange) { addResource(BindingType::Buffer, resource, registerRange); }
- /// Add a texture
- void addTextureResource(TextureResource* resource, const RegisterRange& registerRange) { addResource(BindingType::Texture, resource, registerRange); }
- /// Add combined texture a
- void addCombinedTextureSampler(TextureResource* resource, const SamplerDesc& samplerDesc, const RegisterRange& registerRange);
-
- /// Returns the bind index, that has the bind flag, and indexes the specified register
- int findBindingIndex(Resource::BindFlag::Enum bindFlag, int registerIndex) const;
-
- /// Clear the contents
- void clear();
-
- Slang::List<Binding> m_bindings; ///< All of the bindings in order
- Slang::List<SamplerDesc> m_samplerDescs; ///< Holds the SamplerDesc for the binding - indexed by the descIndex member of Binding
-
- int m_numRenderTargets = 1;
- };
-
- /// Get the Desc used to create this binding
- SLANG_FORCE_INLINE const Desc& getDesc() const { return m_desc; }
-
- protected:
- BindingState(const Desc& desc):
- m_desc(desc)
- {
- }
-
- Desc m_desc;
-};
-
-class Renderer: public Slang::RefObject
-{
-public:
-
- struct Desc
- {
- int width; ///< Width in pixels
- int height; ///< height in pixels
- };
-
- virtual SlangResult initialize(const Desc& desc, void* inWindowHandle) = 0;
-
- virtual void setClearColor(const float color[4]) = 0;
- virtual void clearFrame() = 0;
-
- virtual void presentFrame() = 0;
-
- /// Create a texture resource. initData holds the initialize data to set the contents of the texture when constructed.
- virtual TextureResource* createTextureResource(Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData = nullptr) { return nullptr; }
- /// Create a buffer resource
- virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& desc, const void* initData = nullptr) { return nullptr; }
-
- /// Captures the back buffer and stores the result in surfaceOut. If the surface contains data - it will either be overwritten (if same size and format), or freed and a re-allocated.
- virtual SlangResult captureScreenSurface(Surface& surfaceOut) = 0;
-
- virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) = 0;
- virtual BindingState* createBindingState(const BindingState::Desc& desc) { return nullptr; }
-
- virtual ShaderProgram* createProgram(const ShaderProgram::Desc& desc) = 0;
-
- virtual void* map(BufferResource* buffer, MapFlavor flavor) = 0;
- virtual void unmap(BufferResource* buffer) = 0;
-
- virtual void setInputLayout(InputLayout* inputLayout) = 0;
- virtual void setPrimitiveTopology(PrimitiveTopology topology) = 0;
- virtual void setBindingState(BindingState* state) = 0;
- virtual void setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets) = 0;
-
- inline void setVertexBuffer(UInt slot, BufferResource* buffer, UInt stride, UInt offset = 0);
-
- virtual void setShaderProgram(ShaderProgram* program) = 0;
-
- virtual void draw(UInt vertexCount, UInt startVertex = 0) = 0;
- virtual void dispatchCompute(int x, int y, int z) = 0;
-
- /// Commit any buffered state changes or draw calls.
- /// presentFrame will commitAll implicitly before doing a present
- virtual void submitGpuWork() = 0;
- /// Blocks until Gpu work is complete
- virtual void waitForGpu() = 0;
-
- /// Get the type of this renderer
- virtual RendererType getRendererType() const = 0;
-};
-
-// ----------------------------------------------------------------------------------------
-inline void Renderer::setVertexBuffer(UInt slot, BufferResource* buffer, UInt stride, UInt offset)
-{
- setVertexBuffers(slot, 1, &buffer, &stride, &offset);
-}
-
-/// Functions that are around Renderer and it's types
-struct RendererUtil
-{
- /// Gets the size in bytes of a Format type. Returns 0 if a size is not defined/invalid
- SLANG_FORCE_INLINE static size_t getFormatSize(Format format) { return s_formatSize[int(format)]; }
- /// Given a renderer type, gets a projection style
- static ProjectionStyle getProjectionStyle(RendererType type);
-
- /// Given the projection style returns an 'identity' matrix, which ensures x,y mapping to pixels is the same on all targets
- static void getIdentityProjection(ProjectionStyle style, float projMatrix[16]);
-
- /// Get the binding style from the type
- static BindingStyle getBindingStyle(RendererType type) { return s_rendererTypeToBindingStyle[int(type)]; }
-
- private:
- static void compileTimeAsserts();
- static const uint8_t s_formatSize[]; // Maps Format::XXX to a size in bytes;
- static const BindingStyle s_rendererTypeToBindingStyle[]; ///< Maps a RendererType to a BindingStyle
-};
-
-} // renderer_test
diff --git a/tools/render-test/resource-d3d12.cpp b/tools/render-test/resource-d3d12.cpp
deleted file mode 100644
index 160c7f898..000000000
--- a/tools/render-test/resource-d3d12.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-// resource-d3d12.cpp
-#include "resource-d3d12.h"
-
-namespace renderer_test {
-using namespace Slang;
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! D3D12BarrierSubmitter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-void D3D12BarrierSubmitter::_flush()
-{
- assert(m_numBarriers > 0);
-
- if (m_commandList)
- {
- m_commandList->ResourceBarrier(UINT(m_numBarriers), m_barriers);
- }
- m_numBarriers = 0;
-}
-
-D3D12_RESOURCE_BARRIER& D3D12BarrierSubmitter::_expandOne()
-{
- _flush();
- return m_barriers[m_numBarriers++];
-}
-
-void D3D12BarrierSubmitter::transition(ID3D12Resource* resource, D3D12_RESOURCE_STATES prevState, D3D12_RESOURCE_STATES nextState)
-{
- if (nextState != prevState)
- {
- D3D12_RESOURCE_BARRIER& barrier = expandOne();
-
- const UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
- const D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
-
- ::memset(&barrier, 0, sizeof(barrier));
- barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
- barrier.Flags = flags;
- barrier.Transition.pResource = resource;
- barrier.Transition.StateBefore = prevState;
- barrier.Transition.StateAfter = nextState;
- barrier.Transition.Subresource = subresource;
- }
- else
- {
- if (nextState == D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
- {
- D3D12_RESOURCE_BARRIER& barrier = expandOne();
-
- ::memset(&barrier, 0, sizeof(barrier));
- barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
- barrier.UAV.pResource = resource;
- }
- }
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! D3D12ResourceBase !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-/* static */DXGI_FORMAT D3D12ResourceBase::calcFormat(D3DUtil::UsageType usage, ID3D12Resource* resource)
-{
- return resource ? D3DUtil::calcFormat(usage, resource->GetDesc().Format) : DXGI_FORMAT_UNKNOWN;
-}
-
-void D3D12ResourceBase::transition(D3D12_RESOURCE_STATES nextState, D3D12BarrierSubmitter& submitter)
-{
- // Transition only if there is a resource
- if (m_resource)
- {
- submitter.transition(m_resource, m_state, nextState);
- m_state = nextState;
- }
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! D3D12CounterFence !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-D3D12CounterFence::~D3D12CounterFence()
-{
- if (m_event)
- {
- CloseHandle(m_event);
- }
-}
-
-Result D3D12CounterFence::init(ID3D12Device* device, uint64_t initialValue)
-{
- m_currentValue = initialValue;
-
- SLANG_RETURN_ON_FAIL(device->CreateFence(m_currentValue, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(m_fence.writeRef())));
- // Create an event handle to use for frame synchronization.
- m_event = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
- if (m_event == nullptr)
- {
- Result res = HRESULT_FROM_WIN32(GetLastError());
- return SLANG_FAILED(res) ? res : SLANG_FAIL;
- }
- return SLANG_OK;
-}
-
-UInt64 D3D12CounterFence::nextSignal(ID3D12CommandQueue* commandQueue)
-{
- // Increment the fence value. Save on the frame - we'll know that frame is done when the fence value >=
- m_currentValue++;
- // Schedule a Signal command in the queue.
- Result res = commandQueue->Signal(m_fence, m_currentValue);
- if (SLANG_FAILED(res))
- {
- assert(!"Signal failed");
- }
- return m_currentValue;
-}
-
-void D3D12CounterFence::waitUntilCompleted(uint64_t completedValue)
-{
- // You can only wait for a value that is less than or equal to the current value
- assert(completedValue <= m_currentValue);
-
- // Wait until the previous frame is finished.
- while (m_fence->GetCompletedValue() < completedValue)
- {
- // Make it signal with the current value
- SLANG_ASSERT_VOID_ON_FAIL(m_fence->SetEventOnCompletion(completedValue, m_event));
- WaitForSingleObject(m_event, INFINITE);
- }
-}
-
-void D3D12CounterFence::nextSignalAndWait(ID3D12CommandQueue* commandQueue)
-{
- waitUntilCompleted(nextSignal(commandQueue));
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!! D3D12Resource !!!!!!!!!!!!!!!!!!!!!!!! */
-
-/* static */void D3D12Resource::setDebugName(ID3D12Resource* resource, const char* name)
-{
- if (resource)
- {
- size_t len = ::strlen(name);
- List<wchar_t> buf;
- buf.SetSize(len + 1);
-
- D3DUtil::appendWideChars(name, buf);
- resource->SetName(buf.begin());
- }
-}
-
-void D3D12Resource::setDebugName(const char* name)
-{
- setDebugName(m_resource, name);
-}
-
-void D3D12Resource::setDebugName(const wchar_t* name)
-{
- if (m_resource)
- {
- m_resource->SetName(name);
- }
-}
-
-void D3D12Resource::setResource(ID3D12Resource* resource, D3D12_RESOURCE_STATES initialState)
-{
- if (resource != m_resource)
- {
- if (resource)
- {
- resource->AddRef();
- }
- if (m_resource)
- {
- m_resource->Release();
- }
- m_resource = resource;
- }
- m_prevState = initialState;
- m_state = initialState;
-}
-
-void D3D12Resource::setResourceNull()
-{
- if (m_resource)
- {
- m_resource->Release();
- m_resource = nullptr;
- }
-}
-
-Result D3D12Resource::initCommitted(ID3D12Device* device, const D3D12_HEAP_PROPERTIES& heapProps, D3D12_HEAP_FLAGS heapFlags, const D3D12_RESOURCE_DESC& resourceDesc, D3D12_RESOURCE_STATES initState, const D3D12_CLEAR_VALUE * clearValue)
-{
- setResourceNull();
- ComPtr<ID3D12Resource> resource;
- SLANG_RETURN_ON_FAIL(device->CreateCommittedResource(&heapProps, heapFlags, &resourceDesc, initState, clearValue, IID_PPV_ARGS(resource.writeRef())));
- setResource(resource, initState);
- return SLANG_OK;
-}
-
-ID3D12Resource* D3D12Resource::detach()
-{
- ID3D12Resource* resource = m_resource;
- m_resource = nullptr;
- return resource;
-}
-
-void D3D12Resource::swap(ComPtr<ID3D12Resource>& resourceInOut)
-{
- ID3D12Resource* tmp = m_resource;
- m_resource = resourceInOut.detach();
- resourceInOut.attach(tmp);
-}
-
-void D3D12Resource::setState(D3D12_RESOURCE_STATES state)
-{
- m_prevState = state;
- m_state = state;
-}
-
-} // renderer_test
diff --git a/tools/render-test/resource-d3d12.h b/tools/render-test/resource-d3d12.h
deleted file mode 100644
index 1f0ba638b..000000000
--- a/tools/render-test/resource-d3d12.h
+++ /dev/null
@@ -1,178 +0,0 @@
-// resource-d3d12.h
-#pragma once
-
-#define WIN32_LEAN_AND_MEAN
-#define NOMINMAX
-#include <Windows.h>
-#undef WIN32_LEAN_AND_MEAN
-#undef NOMINMAX
-
-#include <dxgi1_4.h>
-#include <d3d12.h>
-
-#include "../../slang-com-ptr.h"
-#include "d3d-util.h"
-
-namespace renderer_test {
-
-// Enables more conservative barriers - restoring the state of resources after they are used.
-// Should not need to be enabled in normal builds, as the barriers should correctly sync resources
-// If enabling fixes an issue it implies regular barriers are not correctly used.
-#define SLANG_ENABLE_CONSERVATIVE_RESOURCE_BARRIERS 0
-
-struct D3D12BarrierSubmitter
-{
- enum { MAX_BARRIERS = 8 };
-
- /// Expand one space to hold a barrier
- SLANG_FORCE_INLINE D3D12_RESOURCE_BARRIER& expandOne() { return (m_numBarriers < MAX_BARRIERS) ? m_barriers[m_numBarriers++] : _expandOne(); }
- /// Flush barriers to command list
- SLANG_FORCE_INLINE void flush() { if (m_numBarriers > 0) _flush(); }
-
- /// Transition resource from prevState to nextState
- void transition(ID3D12Resource* resource, D3D12_RESOURCE_STATES prevState, D3D12_RESOURCE_STATES nextState);
-
- /// Ctor
- SLANG_FORCE_INLINE D3D12BarrierSubmitter(ID3D12GraphicsCommandList* commandList) : m_numBarriers(0), m_commandList(commandList) { }
- /// Dtor
- SLANG_FORCE_INLINE ~D3D12BarrierSubmitter() { flush(); }
-
-protected:
- D3D12_RESOURCE_BARRIER& _expandOne();
- void _flush();
-
- ID3D12GraphicsCommandList* m_commandList;
- int m_numBarriers;
- D3D12_RESOURCE_BARRIER m_barriers[MAX_BARRIERS];
-};
-
-/*! \brief A class to simplify using Dx12 fences.
-
-A fence is a mechanism to track GPU work. This is achieved by having a counter that the CPU holds
-called the current value. Calling nextSignal will increase the CPU counter, and add a fence
-with that value to the commandQueue. When the GPU has completed all the work before the fence it will
-update the completed value. This is typically used when
-the CPU needs to know the GPU has finished some piece of work has completed. To do this the CPU
-can check the completed value, and when it is greater or equal to the value returned by nextSignal the
-CPU will know that all the work prior to when the nextSignal was added to the queue will have completed.
-
-NOTE! This cannot be used across threads, as for amongst other reasons SetEventOnCompletion
-only works with a single value.
-
-Signal on the CommandQueue updates the fence on the GPU side. Signal on the fence object changes
-the value on the CPU side (not used here).
-
-Useful article describing how Dx12 synchronization works:
-https://msdn.microsoft.com/en-us/library/windows/desktop/dn899217%28v=vs.85%29.aspx
-*/
-class D3D12CounterFence
-{
-public:
- /// Must be called before used
- SlangResult init(ID3D12Device* device, uint64_t initialValue = 0);
- /// Increases the counter, signals the queue and waits for the signal to be hit
- void nextSignalAndWait(ID3D12CommandQueue* queue);
- /// Signals with next counter value. Returns the value the signal was called on
- uint64_t nextSignal(ID3D12CommandQueue* commandQueue);
- /// Get the current value
- SLANG_FORCE_INLINE uint64_t getCurrentValue() const { return m_currentValue; }
- /// Get the completed value
- SLANG_FORCE_INLINE uint64_t getCompletedValue() const { return m_fence->GetCompletedValue(); }
-
- /// Waits for the the specified value
- void waitUntilCompleted(uint64_t completedValue);
-
- /// Ctor
- D3D12CounterFence() :m_event(nullptr), m_currentValue(0) {}
- /// Dtor
- ~D3D12CounterFence();
-
-protected:
- HANDLE m_event;
- Slang::ComPtr<ID3D12Fence> m_fence;
- UINT64 m_currentValue;
-};
-
-/** The base class for resource types allows for tracking of state. It does not allow for setting of the resource though, such that
-an interface can return a D3D12ResourceBase, and a client cant manipulate it's state, but it cannot replace/change the actual resource */
-struct D3D12ResourceBase
-{
- /// Add a transition if necessary to the list
- void transition(D3D12_RESOURCE_STATES nextState, D3D12BarrierSubmitter& submitter);
- /// Get the current state
- SLANG_FORCE_INLINE D3D12_RESOURCE_STATES getState() const { return m_state; }
-
- /// Get the associated resource
- SLANG_FORCE_INLINE ID3D12Resource* getResource() const { return m_resource; }
-
- /// True if a resource is set
- SLANG_FORCE_INLINE bool isSet() const { return m_resource != nullptr; }
-
- /// Coercible into ID3D12Resource
- SLANG_FORCE_INLINE operator ID3D12Resource*() const { return m_resource; }
-
- /// restore previous state
-#if SLANG_ENABLE_CONSERVATIVE_RESOURCE_BARRIERS
- SLANG_FORCE_INLINE Void restore(D3D12BarrierSubmitter& submitter) { transition(m_prevState, submitter); }
-#else
- SLANG_FORCE_INLINE void restore(D3D12BarrierSubmitter& submitter) { SLANG_UNUSED(submitter) }
-#endif
-
- /// Given the usage, flags, and format will return the most suitable format. Will return DXGI_UNKNOWN if combination is not possible
- static DXGI_FORMAT calcFormat(D3DUtil::UsageType usage, ID3D12Resource* resource);
-
- /// Ctor
- SLANG_FORCE_INLINE D3D12ResourceBase() :
- m_state(D3D12_RESOURCE_STATE_COMMON),
- m_prevState(D3D12_RESOURCE_STATE_COMMON),
- m_resource(nullptr)
- {}
-
-protected:
- /// This is protected so as clients cannot slice the class, and so state tracking is lost
- ~D3D12ResourceBase() {}
-
- ID3D12Resource* m_resource; ///< The resource (ref counted)
- D3D12_RESOURCE_STATES m_state; ///< The current tracked expected state, if all associated transitions have completed on ID3D12CommandList
- D3D12_RESOURCE_STATES m_prevState; ///< The previous state
-};
-
-struct D3D12Resource : public D3D12ResourceBase
-{
-
- /// Dtor
- ~D3D12Resource()
- {
- if (m_resource)
- {
- m_resource->Release();
- }
- }
-
- /// Initialize as committed resource
- Slang::Result initCommitted(ID3D12Device* device, const D3D12_HEAP_PROPERTIES& heapProps, D3D12_HEAP_FLAGS heapFlags, const D3D12_RESOURCE_DESC& resourceDesc, D3D12_RESOURCE_STATES initState, const D3D12_CLEAR_VALUE * clearValue);
-
- /// Set a resource with an initial state
- void setResource(ID3D12Resource* resource, D3D12_RESOURCE_STATES initialState);
- /// Make the resource null
- void setResourceNull();
- /// Returns the attached resource (with any ref counts) and sets to nullptr on this.
- ID3D12Resource* detach();
-
- /// Swaps the resource contents with the contents of the smart pointer
- void swap(Slang::ComPtr<ID3D12Resource>& resourceInOut);
-
- /// Sets the current state of the resource (the current state is taken to be the future state once the command list has executed)
- /// NOTE! This must be used with care, otherwise state tracking can be made incorrect.
- void setState(D3D12_RESOURCE_STATES state);
-
- /// Set the debug name on a resource
- static void setDebugName(ID3D12Resource* resource, const char* name);
-
- /// Set the the debug name on the resource
- void setDebugName(const wchar_t* name);
- /// Set the debug name
- void setDebugName(const char* name);
-};
-
-} // renderer_test
diff --git a/tools/render-test/shader-input-layout.h b/tools/render-test/shader-input-layout.h
index 7537527ab..19a7e59d0 100644
--- a/tools/render-test/shader-input-layout.h
+++ b/tools/render-test/shader-input-layout.h
@@ -7,6 +7,8 @@
namespace renderer_test {
+using namespace slang_graphics;
+
enum class ShaderInputType
{
Buffer, Texture, Sampler, CombinedTextureSampler
diff --git a/tools/render-test/surface.cpp b/tools/render-test/surface.cpp
deleted file mode 100644
index eabe555c3..000000000
--- a/tools/render-test/surface.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-// surface.cpp
-#include "surface.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "../../source/core/list.h"
-
-namespace renderer_test {
-using namespace Slang;
-
-class MallocSurfaceAllocator: public SurfaceAllocator
-{
- public:
-
- virtual Slang::Result allocate(int width, int height, Format format, int alignment, Surface& surface) override;
- virtual void deallocate(Surface& surface) override;
-};
-
-static MallocSurfaceAllocator s_mallocSurfaceAllocator;
-
-/// Get the malloc allocator
-/* static */SurfaceAllocator* SurfaceAllocator::getMallocAllocator()
-{
- return &s_mallocSurfaceAllocator;
-}
-
-Slang::Result MallocSurfaceAllocator::allocate(int width, int height, Format format, int alignment, Surface& surface)
-{
- assert(surface.m_data == nullptr);
-
- // Calculate row size
-
- const int rowSizeInBytes = Surface::calcRowSize(format, width);
- const int numRows = Surface::calcNumRows(format, height);
-
- alignment = (alignment <= 0) ? int(sizeof(void*)) : alignment;
- // It must be a power of 2
- assert( ((alignment - 1) & alignment) == 0);
-
- // Align rowSize
- const int alignedRowSizeInBytes = (rowSizeInBytes + alignment - 1) & -alignment;
-
- size_t totalSize = numRows * alignedRowSizeInBytes;
-
- uint8_t* data = (uint8_t*)::malloc(totalSize);
- if (!data)
- {
- return SLANG_E_OUT_OF_MEMORY;
- }
-
- surface.m_data = data;
- surface.m_width = width;
- surface.m_height = height;
- surface.m_format = format;
- surface.m_numRows = numRows;
- surface.m_rowStrideInBytes = alignedRowSizeInBytes;
-
- surface.m_allocator = this;
- return SLANG_OK;
-}
-
-void MallocSurfaceAllocator::deallocate(Surface& surface)
-{
- assert(surface.m_data);
- // Make sure it's not an inverted, cos otherwise m_data is not the start address
- assert(surface.m_rowStrideInBytes > 0);
- ::free(surface.m_data);
-}
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Surface !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-/* static */int Surface::calcRowSize(Format format, int width)
-{
- size_t pixelSize = RendererUtil::getFormatSize(format);
- if (pixelSize == 0)
- {
- return 0;
- }
- return int(pixelSize * width);
-}
-
-/* static */int Surface::calcNumRows(Format format, int height)
-{
- // Don't have any compressed types, so number of rows is same as the height
- return height;
-}
-
-void Surface::init()
-{
- m_width = 0;
- m_height = 0;
- m_format = Format::Unknown;
- m_data = nullptr;
- m_numRows = 0;
- m_rowStrideInBytes = 0;
- // NOTE! does not clear the allocator.
- // If called with an allocation memory will leak!
-}
-
-Surface::~Surface()
-{
- if (m_data && m_allocator)
- {
- m_allocator->deallocate(*this);
- }
-}
-
-void Surface::deallocate()
-{
- if (m_data && m_allocator)
- {
- m_allocator->deallocate(*this);
- init();
- }
-}
-
-Result Surface::allocate(int width, int height, Format format, int alignment, SurfaceAllocator* allocator)
-{
- deallocate();
- allocator = allocator ? allocator : m_allocator;
- if (!allocator)
- {
- // An allocator needs to be set on the surface, or one passed in.
- return SLANG_FAIL;
- }
- return allocator->allocate(width, height, format, alignment, *this);
-}
-
-void Surface::setUnowned(int width, int height, Format format, int strideInBytes, void* data)
-{
- deallocate();
-
- // This is unowned
- m_allocator = nullptr;
-
- m_width = width;
- m_height = height;
- m_format = format;
- m_rowStrideInBytes = strideInBytes;
- m_data = (uint8_t*)data;
-
- m_numRows = Surface::calcNumRows(format, height);
-
- const int rowSizeInBytes = Surface::calcRowSize(format, width);
- assert((strideInBytes > 0 && rowSizeInBytes <= strideInBytes) || (strideInBytes < 0 && rowSizeInBytes <= -strideInBytes));
-}
-
-void Surface::zeroContents()
-{
- const int rowSizeInBytes = Surface::calcRowSize(m_format, m_width);
-
- const int stride = m_rowStrideInBytes;
- uint8_t* dst = m_data;
-
- for (int i = 0; i < m_numRows; i++, dst += stride)
- {
- ::memset(dst, 0, rowSizeInBytes);
- }
-}
-
-void Surface::flipInplaceVertically()
-{
- // Can only flip when m_height matches number of rows
- assert(m_numRows == m_height);
-
- const int rowSizeInBytes = Surface::calcRowSize(m_format, m_width);
- if (rowSizeInBytes <= 0 || m_numRows <= 1)
- {
- return;
- }
-
- uint8_t* top = m_data;
- uint8_t* bottom = m_data + (m_numRows - 1) * m_rowStrideInBytes;
-
- List<uint8_t> bufferList;
- bufferList.SetSize(rowSizeInBytes);
- uint8_t* buffer = bufferList.Buffer();
-
- const int stride = m_rowStrideInBytes;
-
- const int num = m_height >> 1;
- for (int i = 0; i < num; ++i, top += stride, bottom -= stride)
- {
- ::memcpy(buffer, top, rowSizeInBytes);
- ::memcpy(top, bottom, rowSizeInBytes);
- ::memcpy(bottom, buffer, rowSizeInBytes);
- }
-}
-
-SlangResult Surface::set(int width, int height, Format format, int srcRowStride, const void* data, SurfaceAllocator* allocator)
-{
- if (hasContents() && m_width == width && m_height == height && m_format == format)
- {
- // I can just overwrite the contents that is there
- }
- else
- {
- SLANG_RETURN_ON_FAIL(allocate(width, height, format, 0, allocator));
- }
-
- // Okay just need to set the contents
-
- {
- const size_t rowSize = calcRowSize(format, width);
-
- const uint8_t* srcRow = (const uint8_t*)data;
- uint8_t* dstRow = (uint8_t*)m_data;
-
- for (int i = 0; i < m_numRows; i++)
- {
- ::memcpy(dstRow, srcRow, rowSize);
-
- srcRow += srcRowStride;
- dstRow += m_rowStrideInBytes;
- }
- }
-
- return SLANG_OK;
-}
-
-} // renderer_test
diff --git a/tools/render-test/surface.h b/tools/render-test/surface.h
deleted file mode 100644
index c7460238f..000000000
--- a/tools/render-test/surface.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// surface.h
-#pragma once
-
-#include "render.h"
-
-namespace renderer_test {
-
-class Surface;
-
-class SurfaceAllocator
-{
- public:
- virtual Slang::Result allocate(int width, int height, Format format, int alignment, Surface& surface) = 0;
- virtual void deallocate(Surface& surface) = 0;
-
- /// Get the malloc allocator
- static SurfaceAllocator* getMallocAllocator();
-};
-
-class Surface
-{
- public:
-
- enum
- {
- kDefaultAlignment = sizeof(void*)
- };
-
- /// Allocate
- Slang::Result allocate(int width, int height, Format format, int alignment = kDefaultAlignment, SurfaceAllocator* allocator = nullptr);
-
- /// Deallocate contents
- void deallocate();
- /// Initialize contents (zero sized, no data). Note that the allocator pointer is left as is
- void init();
-
- /// Set unowned
- void setUnowned(int width, int height, Format format, int strideInBytes, void* data);
-
- /// Set the contents - the memory will be owned by this surface (ie will be freed by the allocator when goes out of scope or is deallocated)
- Slang::Result set(int width, int height, Format format, int strideInBytes, const void* data, SurfaceAllocator* allocator);
-
- template <typename T>
- T* calcNextRow(T* ptr) const { return (T*)calcNextRow((void*)ptr); }
- template <typename T>
- const T* calcNextRow(const T* ptr) const { return (const T*)calcNextRow((const void*)ptr); }
-
- void* calcNextRow(void* ptr) const { return (void*)(((uint8_t*)ptr) + m_rowStrideInBytes); }
- const void* calcNextRow(const void* ptr) const { return (const void*)(((const uint8_t*)ptr) + m_rowStrideInBytes); }
-
- /// Writes zero to all of the contents
- void zeroContents();
-
- /// Flips the contents vertically in place
- void flipInplaceVertically();
-
- /// True if has some contents
- bool hasContents() const { return m_data != nullptr; }
-
- /// Ctor
- Surface() :
- m_allocator(nullptr)
- {
- init();
- }
- /// Dtor
- ~Surface();
-
- /// Get the size of the row in bytes
- static int calcRowSize(Format format, int width);
- /// Calculates the number of rows
- static int calcNumRows(Format format, int height);
-
- int m_width;
- int m_height;
- Format m_format;
-
- uint8_t* m_data; /// The data that makes up the image. If nullptr, has no data. Pointer to first 'row' of the image.
-
- int m_numRows; ///< Total amount of rows (typically same as height, but in compressed formats may be less)
- int m_rowStrideInBytes; ///< The number of bytes between rows
-
- SurfaceAllocator* m_allocator; ///< Can be null if so contents is 'unowned', if set
-};
-
-} // renderer_test
diff --git a/tools/render-test/vk-api.cpp b/tools/render-test/vk-api.cpp
deleted file mode 100644
index df222d8ad..000000000
--- a/tools/render-test/vk-api.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-// vk-api.cpp
-#include "vk-api.h"
-
-#include "../../source/core/list.h"
-
-namespace renderer_test {
-using namespace Slang;
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! VulkanApi !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-#define VK_API_CHECK_FUNCTION(x) && (x != nullptr)
-#define VK_API_CHECK_FUNCTIONS(FUNCTION_LIST) true FUNCTION_LIST(VK_API_CHECK_FUNCTION)
-
-bool VulkanApi::areDefined(ProcType type) const
-{
- switch (type)
- {
- case ProcType::Global: return VK_API_CHECK_FUNCTIONS(VK_API_ALL_GLOBAL_PROCS);
- case ProcType::Instance: return VK_API_CHECK_FUNCTIONS(VK_API_ALL_INSTANCE_PROCS);
- case ProcType::Device: return VK_API_CHECK_FUNCTIONS(VK_API_ALL_DEVICE_PROCS);
- default:
- {
- assert(!"Unhandled type");
- return false;
- }
- }
-}
-
-Slang::Result VulkanApi::initGlobalProcs(const VulkanModule& module)
-{
-#define VK_API_GET_GLOBAL_PROC(x) x = (PFN_##x)module.getFunction(#x);
-
- // Initialize all the global functions
- VK_API_ALL_GLOBAL_PROCS(VK_API_GET_GLOBAL_PROC)
-
- if (!areDefined(ProcType::Global))
- {
- return SLANG_FAIL;
- }
- m_module = &module;
- return SLANG_OK;
-}
-
-Slang::Result VulkanApi::initInstanceProcs(VkInstance instance)
-{
- assert(instance && vkGetInstanceProcAddr != nullptr);
-
-#define VK_API_GET_INSTANCE_PROC(x) x = (PFN_##x)vkGetInstanceProcAddr(instance, #x);
-
- VK_API_ALL_INSTANCE_PROCS(VK_API_GET_INSTANCE_PROC)
-
- if (!areDefined(ProcType::Instance))
- {
- return SLANG_FAIL;
- }
-
- m_instance = instance;
- return SLANG_OK;
-}
-
-Slang::Result VulkanApi::initPhysicalDevice(VkPhysicalDevice physicalDevice)
-{
- assert(m_physicalDevice == VK_NULL_HANDLE);
- m_physicalDevice = physicalDevice;
-
- vkGetPhysicalDeviceProperties(m_physicalDevice, &m_deviceProperties);
- vkGetPhysicalDeviceFeatures(m_physicalDevice, &m_deviceFeatures);
- vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &m_deviceMemoryProperties);
-
- return SLANG_OK;
-}
-
-Slang::Result VulkanApi::initDeviceProcs(VkDevice device)
-{
- assert(m_instance && device && vkGetDeviceProcAddr != nullptr);
-
-#define VK_API_GET_DEVICE_PROC(x) x = (PFN_##x)vkGetDeviceProcAddr(device, #x);
-
- VK_API_ALL_DEVICE_PROCS(VK_API_GET_DEVICE_PROC)
-
- if (!areDefined(ProcType::Device))
- {
- return SLANG_FAIL;
- }
-
- m_device = device;
- return SLANG_OK;
-}
-
-int VulkanApi::findMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties) const
-{
- assert(typeBits);
-
- const int numMemoryTypes = int(m_deviceMemoryProperties.memoryTypeCount);
-
- // bit holds current test bit against typeBits. Ie bit == 1 << typeBits
-
- uint32_t bit = 1;
- for (int i = 0; i < numMemoryTypes; ++i, bit += bit)
- {
- auto const& memoryType = m_deviceMemoryProperties.memoryTypes[i];
- if ((typeBits & bit) && (memoryType.propertyFlags & properties) == properties)
- {
- return i;
- }
- }
-
- //assert(!"failed to find a usable memory type");
- return -1;
-}
-
-int VulkanApi::findQueue(VkQueueFlags reqFlags) const
-{
- assert(m_physicalDevice != VK_NULL_HANDLE);
-
- uint32_t numQueueFamilies = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &numQueueFamilies, nullptr);
-
- Slang::List<VkQueueFamilyProperties> queueFamilies;
- queueFamilies.SetSize(numQueueFamilies);
- vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &numQueueFamilies, queueFamilies.Buffer());
-
- // Find a queue that can service our needs
- //VkQueueFlags reqQueueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
-
- int queueFamilyIndex = -1;
- for (int i = 0; i < int(numQueueFamilies); ++i)
- {
- if ((queueFamilies[i].queueFlags & reqFlags) == reqFlags)
- {
- return i;
- }
- }
-
- return -1;
-}
-
-} // renderer_test
diff --git a/tools/render-test/vk-api.h b/tools/render-test/vk-api.h
deleted file mode 100644
index 521d6301d..000000000
--- a/tools/render-test/vk-api.h
+++ /dev/null
@@ -1,196 +0,0 @@
-// vk-api.h
-#pragma once
-
-#include "vk-module.h"
-
-namespace renderer_test {
-
-#define VK_API_GLOBAL_PROCS(x) \
- x(vkGetInstanceProcAddr) \
- x(vkCreateInstance) \
- /* */
-
-#define VK_API_INSTANCE_PROCS(x) \
- x(vkCreateDevice) \
- x(vkCreateDebugReportCallbackEXT) \
- x(vkDestroyDebugReportCallbackEXT) \
- x(vkDebugReportMessageEXT) \
- x(vkEnumeratePhysicalDevices) \
- x(vkGetPhysicalDeviceProperties) \
- x(vkGetPhysicalDeviceFeatures) \
- x(vkGetPhysicalDeviceMemoryProperties) \
- x(vkGetPhysicalDeviceQueueFamilyProperties) \
- x(vkGetPhysicalDeviceFormatProperties) \
- x(vkGetDeviceProcAddr) \
- /* */
-
-#define VK_API_DEVICE_PROCS(x) \
- x(vkCreateDescriptorPool) \
- x(vkDestroyDescriptorPool) \
- x(vkGetDeviceQueue) \
- x(vkQueueSubmit) \
- x(vkQueueWaitIdle) \
- x(vkCreateBuffer) \
- x(vkAllocateMemory) \
- x(vkMapMemory) \
- x(vkUnmapMemory) \
- x(vkCmdCopyBuffer) \
- x(vkDestroyBuffer) \
- x(vkFreeMemory) \
- x(vkCreateDescriptorSetLayout) \
- x(vkDestroyDescriptorSetLayout) \
- x(vkAllocateDescriptorSets) \
- x(vkUpdateDescriptorSets) \
- x(vkCreatePipelineLayout) \
- x(vkDestroyPipelineLayout) \
- x(vkCreateComputePipelines) \
- x(vkCreateGraphicsPipelines) \
- x(vkDestroyPipeline) \
- x(vkCreateShaderModule) \
- x(vkDestroyShaderModule) \
- x(vkCreateFramebuffer) \
- x(vkDestroyFramebuffer) \
- x(vkCreateImage) \
- x(vkDestroyImage) \
- x(vkCreateImageView) \
- x(vkDestroyImageView) \
- x(vkCreateRenderPass) \
- x(vkDestroyRenderPass) \
- x(vkCreateCommandPool) \
- x(vkDestroyCommandPool) \
- x(vkCreateSampler) \
- x(vkDestroySampler) \
- x(vkCreateBufferView) \
- x(vkDestroyBufferView) \
- \
- x(vkGetBufferMemoryRequirements) \
- x(vkGetImageMemoryRequirements) \
- \
- x(vkCmdBindPipeline) \
- x(vkCmdBindDescriptorSets) \
- x(vkCmdDispatch) \
- x(vkCmdDraw) \
- x(vkCmdSetScissor) \
- x(vkCmdSetViewport) \
- x(vkCmdBindVertexBuffers) \
- x(vkCmdBindIndexBuffer) \
- x(vkCmdBeginRenderPass) \
- x(vkCmdEndRenderPass) \
- x(vkCmdPipelineBarrier) \
- x(vkCmdCopyBufferToImage)\
- \
- x(vkCreateFence) \
- x(vkDestroyFence) \
- x(vkResetFences) \
- x(vkGetFenceStatus) \
- x(vkWaitForFences) \
- \
- x(vkCreateSemaphore) \
- x(vkDestroySemaphore) \
- \
- x(vkCreateEvent) \
- x(vkDestroyEvent) \
- x(vkGetEventStatus) \
- x(vkSetEvent) \
- x(vkResetEvent) \
- \
- x(vkFreeCommandBuffers) \
- x(vkAllocateCommandBuffers) \
- x(vkBeginCommandBuffer) \
- x(vkEndCommandBuffer) \
- x(vkResetCommandBuffer) \
- \
- x(vkBindImageMemory) \
- x(vkBindBufferMemory) \
- /* */
-
-#if SLANG_WINDOWS_FAMILY
-# define VK_API_INSTANCE_PLATFORM_KHR_PROCS(x) \
- x(vkCreateWin32SurfaceKHR) \
- /* */
-#else
-# define VK_API_INSTANCE_PLATFORM_KHR_PROCS(x) \
- x(vkCreateXlibSurfaceKHR) \
- /* */
-#endif
-
-#define VK_API_INSTANCE_KHR_PROCS(x) \
- VK_API_INSTANCE_PLATFORM_KHR_PROCS(x) \
- x(vkGetPhysicalDeviceSurfaceSupportKHR) \
- x(vkGetPhysicalDeviceSurfaceFormatsKHR) \
- x(vkGetPhysicalDeviceSurfacePresentModesKHR) \
- x(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \
- x(vkDestroySurfaceKHR) \
- /* */
-
-#define VK_API_DEVICE_KHR_PROCS(x) \
- x(vkQueuePresentKHR) \
- x(vkCreateSwapchainKHR) \
- x(vkGetSwapchainImagesKHR) \
- x(vkDestroySwapchainKHR) \
- x(vkAcquireNextImageKHR) \
- /* */
-
-#define VK_API_ALL_GLOBAL_PROCS(x) \
- VK_API_GLOBAL_PROCS(x)
-
-#define VK_API_ALL_INSTANCE_PROCS(x) \
- VK_API_INSTANCE_PROCS(x) \
- VK_API_INSTANCE_KHR_PROCS(x)
-
-#define VK_API_ALL_DEVICE_PROCS(x) \
- VK_API_DEVICE_PROCS(x) \
- VK_API_DEVICE_KHR_PROCS(x)
-
-#define VK_API_ALL_PROCS(x) \
- VK_API_ALL_GLOBAL_PROCS(x) \
- VK_API_ALL_INSTANCE_PROCS(x) \
- VK_API_ALL_DEVICE_PROCS(x) \
- /* */
-
-#define VK_API_DECLARE_PROC(NAME) PFN_##NAME NAME = nullptr;
-
-struct VulkanApi
-{
- VK_API_ALL_PROCS(VK_API_DECLARE_PROC)
-
- enum class ProcType
- {
- Global,
- Instance,
- Device,
- };
-
- /// Returns true if all the functions in the class are defined
- bool areDefined(ProcType type) const;
-
- /// Sets up global parameters
- Slang::Result initGlobalProcs(const VulkanModule& module);
- /// Initialize the instance functions
- Slang::Result initInstanceProcs(VkInstance instance);
-
- /// Called before initDevice
- Slang::Result initPhysicalDevice(VkPhysicalDevice physicalDevice);
-
- /// Initialize the device functions
- Slang::Result initDeviceProcs(VkDevice device);
-
- /// Type bits control which indices are tested against bit 0 for testing at index 0
- /// properties - a memory type must have all the bits set as passed in
- /// Returns -1 if couldn't find an appropriate memory type index
- int findMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties) const;
-
- /// Given queue required flags, finds a queue
- int findQueue(VkQueueFlags reqFlags) const;
-
- const VulkanModule* m_module = nullptr; ///< Module this was all loaded from
- VkInstance m_instance = VK_NULL_HANDLE;
- VkDevice m_device = VK_NULL_HANDLE;
- VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
-
- VkPhysicalDeviceProperties m_deviceProperties;
- VkPhysicalDeviceFeatures m_deviceFeatures;
- VkPhysicalDeviceMemoryProperties m_deviceMemoryProperties;
-};
-
-} // renderer_test
diff --git a/tools/render-test/vk-device-queue.cpp b/tools/render-test/vk-device-queue.cpp
deleted file mode 100644
index d40442c22..000000000
--- a/tools/render-test/vk-device-queue.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-// vk-device-queue.cpp
-#include "vk-device-queue.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-
-namespace renderer_test {
-using namespace Slang;
-
-VulkanDeviceQueue::~VulkanDeviceQueue()
-{
- for (int i = 0; i < int(EventType::CountOf); ++i)
- {
- m_api->vkDestroySemaphore(m_api->m_device, m_semaphores[i], nullptr);
- }
-
- for (int i = 0; i < m_numCommandBuffers; i++)
- {
- m_api->vkFreeCommandBuffers(m_api->m_device, m_commandPool, 1, &m_commandBuffers[i]);
- m_api->vkDestroyFence(m_api->m_device, m_fences[i].fence, nullptr);
- }
- m_api->vkDestroyCommandPool(m_api->m_device, m_commandPool, nullptr);
-}
-
-SlangResult VulkanDeviceQueue::init(const VulkanApi& api, VkQueue queue, int queueIndex)
-{
- assert(m_api == nullptr);
- m_api = &api;
-
- for (int i = 0; i < int(EventType::CountOf); ++i)
- {
- m_semaphores[i] = VK_NULL_HANDLE;
- m_currentSemaphores[i] = VK_NULL_HANDLE;
- }
-
- m_numCommandBuffers = kMaxCommandBuffers;
- m_queueIndex = queueIndex;
-
- m_queue = queue;
-
- VkCommandPoolCreateInfo poolCreateInfo = {};
- poolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- poolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
-
- poolCreateInfo.queueFamilyIndex = queueIndex;
-
- api.vkCreateCommandPool(api.m_device, &poolCreateInfo, nullptr, &m_commandPool);
-
- VkCommandBufferAllocateInfo commandInfo = {};
- commandInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- commandInfo.commandPool = m_commandPool;
- commandInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- commandInfo.commandBufferCount = 1;
-
- VkFenceCreateInfo fenceCreateInfo = {};
- fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- fenceCreateInfo.flags = 0; // VK_FENCE_CREATE_SIGNALED_BIT;
-
- for (int i = 0; i < m_numCommandBuffers; i++)
- {
- Fence& fence = m_fences[i];
-
- api.vkAllocateCommandBuffers(api.m_device, &commandInfo, &m_commandBuffers[i]);
-
- api.vkCreateFence(api.m_device, &fenceCreateInfo, nullptr, &fence.fence);
- fence.active = false;
- fence.value = 0;
- }
-
- VkSemaphoreCreateInfo semaphoreCreateInfo = {};
- semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
-
- for (int i = 0; i < int(EventType::CountOf); ++i)
- {
- api.vkCreateSemaphore(api.m_device, &semaphoreCreateInfo, nullptr, &m_semaphores[i]);
- }
-
- // Second step of flush to prime command buffer
- flushStepB();
-
- return SLANG_OK;
-}
-
-void VulkanDeviceQueue::flushStepA()
-{
- m_api->vkEndCommandBuffer(m_commandBuffer);
-
- VkPipelineStageFlags stageFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
-
- VkSubmitInfo submitInfo = {};
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
-
- // Wait semaphores
- if (isCurrent(EventType::BeginFrame))
- {
- submitInfo.waitSemaphoreCount = 1;
- submitInfo.pWaitSemaphores = &m_currentSemaphores[int(EventType::BeginFrame)];
- }
-
- submitInfo.pWaitDstStageMask = &stageFlags;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &m_commandBuffer;
-
- // Signal semaphores
- if (isCurrent(EventType::EndFrame))
- {
- submitInfo.signalSemaphoreCount = 1;
- submitInfo.pSignalSemaphores = &m_currentSemaphores[int(EventType::EndFrame)];
- }
-
- Fence& fence = m_fences[m_commandBufferIndex];
-
- m_api->vkQueueSubmit(m_queue, 1, &submitInfo, fence.fence);
-
- // mark signaled fence value
- fence.value = m_nextFenceValue;
- fence.active = true;
-
- // increment fence value
- m_nextFenceValue++;
-
- // No longer waiting on this semaphore
- makeCompleted(EventType::BeginFrame);
-}
-
-void VulkanDeviceQueue::_updateFenceAtIndex( int fenceIndex, bool blocking)
-{
- Fence& fence = m_fences[fenceIndex];
-
- if (fence.active)
- {
- uint64_t timeout = blocking ? ~uint64_t(0) : 0;
-
- if (VK_SUCCESS == m_api->vkWaitForFences(m_api->m_device, 1, &fence.fence, VK_TRUE, timeout))
- {
- m_api->vkResetFences(m_api->m_device, 1, &fence.fence);
-
- fence.active = false;
-
- if (fence.value > m_lastFenceCompleted)
- {
- m_lastFenceCompleted = fence.value;
- }
- }
- }
-}
-
-void VulkanDeviceQueue::flushStepB()
-{
- m_commandBufferIndex = (m_commandBufferIndex + 1) % m_numCommandBuffers;
- m_commandBuffer = m_commandBuffers[m_commandBufferIndex];
-
- // non-blocking update of fence values
- for (int i = 0; i < m_numCommandBuffers; ++i)
- {
- _updateFenceAtIndex(i, false);
- }
-
- // blocking update of fence values
- _updateFenceAtIndex(m_commandBufferIndex, true);
-
- m_api->vkResetCommandBuffer(m_commandBuffer, 0);
-
- //m_api.vkResetCommandPool(m_api->m_device, m_commandPool, 0);
-
- VkCommandBufferBeginInfo beginInfo = {};
- beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
-
- m_api->vkBeginCommandBuffer(m_commandBuffer, &beginInfo);
-}
-
-void VulkanDeviceQueue::flush()
-{
- flushStepA();
- flushStepB();
-}
-
-void VulkanDeviceQueue::flushAndWait()
-{
- flush();
- waitForIdle();
-}
-
-VkSemaphore VulkanDeviceQueue::makeCurrent(EventType eventType)
-{
- assert(!isCurrent(eventType));
- VkSemaphore semaphore = m_semaphores[int(eventType)];
- m_currentSemaphores[int(eventType)] = semaphore;
- return semaphore;
-}
-
-void VulkanDeviceQueue::makeCompleted(EventType eventType)
-{
- m_currentSemaphores[int(eventType)] = VK_NULL_HANDLE;
-}
-
-} // renderer_test
diff --git a/tools/render-test/vk-device-queue.h b/tools/render-test/vk-device-queue.h
deleted file mode 100644
index 8381f5166..000000000
--- a/tools/render-test/vk-device-queue.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// vk-swap-chain.h
-#pragma once
-
-#include "vk-api.h"
-
-namespace renderer_test {
-
-struct VulkanDeviceQueue
-{
- enum
- {
- kMaxCommandBuffers = 8,
- };
-
- enum class EventType
- {
- BeginFrame,
- EndFrame,
- CountOf,
- };
-
- /// Initialize - must be called before anything else can be done
- SlangResult init(const VulkanApi& api, VkQueue queue, int queueIndex);
-
- /// Flushes the current command list, and steps to next (internally this is equivalent to a stepA followed by stepB)
- void flush();
- /// Performs a full flush, and then waits for idle.
- void flushAndWait();
-
- /// Blocks until all work submitted to GPU has completed
- void waitForIdle() { m_api->vkQueueWaitIdle(m_queue); }
-
- /// Get the graphics queue index (as set on init)
- int getQueueIndex() const { return m_queueIndex; }
-
- /// Make the specified event 'current' - meaning it's semaphore must be waited on
- VkSemaphore makeCurrent(EventType eventType);
- /// Makes the event no longer required to be waited on
- void makeCompleted(EventType eventType);
- /// Returns true if the event is already current
- SLANG_FORCE_INLINE bool isCurrent(EventType eventType) const { return m_currentSemaphores[int(eventType)] != VK_NULL_HANDLE; }
-
- /// Get the command buffer
- VkCommandBuffer getCommandBuffer() const { return m_commandBuffer; }
-
- /// Get the queue
- VkQueue getQueue() const { return m_queue; }
-
- /// Get the API
- const VulkanApi* getApi() const { return m_api; }
-
- /// Flushes the current command list
- void flushStepA();
- /// Steps to next command buffer and opens. May block if command buffer is still in use
- void flushStepB();
-
- /// Dtor
- ~VulkanDeviceQueue();
-
- protected:
-
- struct Fence
- {
- VkFence fence;
- bool active;
- uint64_t value;
- };
-
- void _updateFenceAtIndex(int fenceIndex, bool blocking);
-
- VkQueue m_queue = VK_NULL_HANDLE;
-
- VkCommandPool m_commandPool = VK_NULL_HANDLE;
- int m_numCommandBuffers = 0;
- int m_commandBufferIndex = 0;
- // There are the same amount of command buffers as fences
- VkCommandBuffer m_commandBuffers[kMaxCommandBuffers] = { VK_NULL_HANDLE };
-
- Fence m_fences[kMaxCommandBuffers] = { {VK_NULL_HANDLE, 0, 0u} };
-
- VkCommandBuffer m_commandBuffer = VK_NULL_HANDLE;
-
- VkSemaphore m_semaphores[int(EventType::CountOf)];
- VkSemaphore m_currentSemaphores[int(EventType::CountOf)];
-
- uint64_t m_lastFenceCompleted = 1;
- uint64_t m_nextFenceValue = 2;
-
- int m_queueIndex = 0;
-
- const VulkanApi* m_api = nullptr;
-};
-
-} // renderer_test
diff --git a/tools/render-test/vk-module.cpp b/tools/render-test/vk-module.cpp
deleted file mode 100644
index e98bd08cd..000000000
--- a/tools/render-test/vk-module.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-// module.cpp
-#include "vk-module.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-
-#if SLANG_WINDOWS_FAMILY
-# include <windows.h>
-#else
-# include <dlfcn.h>
-#endif
-
-namespace renderer_test {
-using namespace Slang;
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! VulkanModule !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-Slang::Result VulkanModule::init()
-{
- if (isInitialized())
- {
- destroy();
- return SLANG_OK;
- }
-
- const char* dynamicLibraryName = "Unknown";
-
-#if SLANG_WINDOWS_FAMILY
- dynamicLibraryName = "vulkan-1.dll";
- HMODULE module = ::LoadLibraryA(dynamicLibraryName);
- m_module = (void*)module;
-#else
- dynamicLibraryName = "libvulkan.so.1";
- m_module = dlopen(dynamicLibraryName, RTLD_NOW);
-#endif
-
- if (!m_module)
- {
- fprintf(stderr, "error: failed load '%s'\n", dynamicLibraryName);
- return SLANG_FAIL;
- }
-
- return SLANG_OK;
-}
-
-PFN_vkVoidFunction VulkanModule::getFunction(const char* name) const
-{
- assert(m_module);
- if (!m_module)
- {
- return nullptr;
- }
-#if SLANG_WINDOWS_FAMILY
- return (PFN_vkVoidFunction)::GetProcAddress((HMODULE)m_module, name);
-#else
- return (PFN_vkVoidFunction)dlsym(m_module, name);
-#endif
-}
-
-void VulkanModule::destroy()
-{
- if (!isInitialized())
- {
- return;
- }
-
-#if SLANG_WINDOWS_FAMILY
- ::FreeLibrary((HMODULE)m_module);
-#else
- dlclose(m_module);
-#endif
- m_module = nullptr;
-}
-
-} // renderer_test
diff --git a/tools/render-test/vk-module.h b/tools/render-test/vk-module.h
deleted file mode 100644
index 0aed2303f..000000000
--- a/tools/render-test/vk-module.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// vk-module.h
-#pragma once
-
-#include "../../slang.h"
-
-#include "../../slang-com-helper.h"
-
-#if SLANG_WINDOWS_FAMILY
-# define VK_USE_PLATFORM_WIN32_KHR 1
-#else
-# define VK_USE_PLATFORM_XLIB_KHR 1
-#endif
-
-#define VK_NO_PROTOTYPES
-#include <vulkan/vulkan.h>
-
-namespace renderer_test {
-
-struct VulkanModule
-{
- /// true if has been initialized
- SLANG_FORCE_INLINE bool isInitialized() const { return m_module != nullptr; }
-
- /// Get a function by name
- PFN_vkVoidFunction getFunction(const char* name) const;
-
- /// Initialize
- Slang::Result init();
- /// Destroy
- void destroy();
-
- /// Dtor
- ~VulkanModule() { destroy(); }
-
- protected:
- void* m_module = nullptr;
-};
-
-} // renderer_test
diff --git a/tools/render-test/vk-swap-chain.cpp b/tools/render-test/vk-swap-chain.cpp
deleted file mode 100644
index 7b8b6221c..000000000
--- a/tools/render-test/vk-swap-chain.cpp
+++ /dev/null
@@ -1,421 +0,0 @@
-// vk-swap-chain.cpp
-#include "vk-swap-chain.h"
-
-#include "vk-util.h"
-
-#include "../../source/core/list.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-
-namespace renderer_test {
-using namespace Slang;
-
-static int _indexOf(List<VkSurfaceFormatKHR>& formatsIn, VkFormat format)
-{
- const int numFormats = int(formatsIn.Count());
- const VkSurfaceFormatKHR* formats = formatsIn.Buffer();
-
- for (int i = 0; i < numFormats; ++i)
- {
- if (formats[i].format == format)
- {
- return i;
- }
- }
- return -1;
-}
-
-SlangResult VulkanSwapChain::init(VulkanDeviceQueue* deviceQueue, const Desc& descIn, const PlatformDesc* platformDescIn)
-{
- assert(platformDescIn);
-
- m_deviceQueue = deviceQueue;
- m_api = deviceQueue->getApi();
-
- // Make sure it's not set initially
- m_format = VK_FORMAT_UNDEFINED;
-
- Desc desc(descIn);
-
-#if SLANG_WINDOWS_FAMILY
- const WinPlatformDesc* platformDesc = static_cast<const WinPlatformDesc*>(platformDescIn);
- _setPlatformDesc(*platformDesc);
-
- VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = {};
- surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
- surfaceCreateInfo.hinstance = platformDesc->m_hinstance;
- surfaceCreateInfo.hwnd = platformDesc->m_hwnd;
-
- SLANG_VK_RETURN_ON_FAIL(m_api->vkCreateWin32SurfaceKHR(m_api->m_instance, &surfaceCreateInfo, nullptr, &m_surface));
-#else
- const XPlatformDesc* platformDesc = static_cast<const XPlatformDesc*>(platformDescIn);
- _setPlatformDesc(*platformDesc);
-
- VkXlibSurfaceCreateInfoKHR surfaceCreateInfo = {};
- surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
- surfaceCreateInfo.dpy = platformDesc->m_display;
- surfaceCreateInfo.window = platformDesc->m_window;
-
- SLANG_VK_RETURN_ON_FAIL(m_api->vkCreateXlibSurfaceKHR(m_api->m_instance, &surfaceCreateInfo, nullptr, &m_surface));
-#endif
-
- VkBool32 supported = false;
- m_api->vkGetPhysicalDeviceSurfaceSupportKHR(m_api->m_physicalDevice, deviceQueue->getQueueIndex(), m_surface, &supported);
-
- uint32_t numSurfaceFormats = 0;
- List<VkSurfaceFormatKHR> surfaceFormats;
- m_api->vkGetPhysicalDeviceSurfaceFormatsKHR(m_api->m_physicalDevice, m_surface, &numSurfaceFormats, nullptr);
- surfaceFormats.SetSize(int(numSurfaceFormats));
- m_api->vkGetPhysicalDeviceSurfaceFormatsKHR(m_api->m_physicalDevice, m_surface, &numSurfaceFormats, surfaceFormats.Buffer());
-
- // Look for a suitable format
- List<VkFormat> formats;
- formats.Add(VulkanUtil::getVkFormat(desc.m_format));
- // HACK! To check for a different format if couldn't be found
- if (descIn.m_format == Format::RGBA_Unorm_UInt8)
- {
- formats.Add(VK_FORMAT_B8G8R8A8_UNORM);
- }
-
- for(int i = 0; i < int(formats.Count()); ++i)
- {
- VkFormat format = formats[i];
- if (_indexOf(surfaceFormats, format) >= 0)
- {
- m_format = format;
- }
- }
-
- if (m_format == VK_FORMAT_UNDEFINED)
- {
- return SLANG_FAIL;
- }
-
- // Save the desc
- m_desc = desc;
-
- SLANG_RETURN_ON_FAIL(_createSwapChain());
-
- m_desc = desc;
- return SLANG_OK;
-}
-
-void VulkanSwapChain::getWindowSize(int* widthOut, int* heightOut) const
-{
-#if SLANG_WINDOWS_FAMILY
- auto platformDesc = _getPlatformDesc<WinPlatformDesc>();
-
- RECT rc;
- ::GetClientRect(platformDesc->m_hwnd, &rc);
- *widthOut = rc.right - rc.left;
- *heightOut = rc.bottom - rc.top;
-#else
- auto platformDesc = _getPlatformDesc<XPlatformDesc>();
-
- XWindowAttributes winAttr = {};
- XGetWindowAttributes(platformDesc->m_display, platformDesc->m_window, &winAttr);
-
- *widthOut = winAttr.width;
- *heightOut = winAttr.height;
-#endif
-}
-
-SlangResult VulkanSwapChain::_createFrameBuffers(VkRenderPass renderPass)
-{
- assert(renderPass != VK_NULL_HANDLE);
-
- for (int i = 0; i < int(m_images.Count()); ++i)
- {
- Image& image = m_images[i];
- VkImageView attachments[] =
- {
- image.m_imageView
- };
-
- VkFramebufferCreateInfo framebufferInfo = {};
- framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- framebufferInfo.renderPass = renderPass;
- framebufferInfo.attachmentCount = 1;
- framebufferInfo.pAttachments = attachments;
- framebufferInfo.width = m_width;
- framebufferInfo.height = m_height;
- framebufferInfo.layers = 1;
-
- SLANG_VK_RETURN_ON_FAIL(m_api->vkCreateFramebuffer(m_api->m_device, &framebufferInfo, nullptr, &image.m_frameBuffer));
- }
-
- return SLANG_OK;
-}
-
-void VulkanSwapChain::_destroyFrameBuffers()
-{
- for (int i = 0; i < int(m_images.Count()); ++i)
- {
- Image& image = m_images[i];
- if (image.m_frameBuffer != VK_NULL_HANDLE)
- {
- m_api->vkDestroyFramebuffer(m_api->m_device, image.m_frameBuffer, nullptr);
- image.m_frameBuffer = VK_NULL_HANDLE;
- }
- }
-}
-
-SlangResult VulkanSwapChain::createFrameBuffers(VkRenderPass renderPass)
-{
- if (m_renderPass != VK_NULL_HANDLE)
- {
- _destroyFrameBuffers();
- m_renderPass = VK_NULL_HANDLE;
- }
- if (renderPass != VK_NULL_HANDLE)
- {
- SLANG_RETURN_ON_FAIL(_createFrameBuffers(renderPass));
- }
- m_renderPass = renderPass;
- return SLANG_OK;
-}
-
-SlangResult VulkanSwapChain::_createSwapChain()
-{
- if (hasValidSwapChain())
- {
- return SLANG_OK;
- }
-
- int width, height;
- getWindowSize(&width, &height);
-
- VkExtent2D imageExtent = {};
- imageExtent.width = width;
- imageExtent.height = height;
-
- m_width = width;
- m_height = height;
-
- // catch this before throwing error
- if (m_width == 0 || m_height == 0)
- {
- return SLANG_FAIL;
- }
-
- // It is necessary to query the caps -> otherwise the LunarG verification layer will issue an error
- {
- VkSurfaceCapabilitiesKHR surfaceCaps;
-
- SLANG_VK_RETURN_ON_FAIL(m_api->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_api->m_physicalDevice, m_surface, &surfaceCaps));
- }
-
- List<VkPresentModeKHR> presentModes;
- uint32_t numPresentModes = 0;
- m_api->vkGetPhysicalDeviceSurfacePresentModesKHR(m_api->m_physicalDevice, m_surface, &numPresentModes, nullptr);
- presentModes.SetSize(numPresentModes);
- m_api->vkGetPhysicalDeviceSurfacePresentModesKHR(m_api->m_physicalDevice, m_surface, &numPresentModes, presentModes.Buffer());
-
- {
- int numCheckPresentOptions = 3;
- VkPresentModeKHR presentOptions[] = { VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR };
- if (m_vsync)
- {
- presentOptions[0] = VK_PRESENT_MODE_FIFO_KHR;
- presentOptions[1] = VK_PRESENT_MODE_IMMEDIATE_KHR;
- presentOptions[2] = VK_PRESENT_MODE_MAILBOX_KHR;
- }
-
- m_presentMode = VK_PRESENT_MODE_MAX_ENUM_KHR; // Invalid
-
- // Find the first option that's available on the device
- for (int j = 0; j < numCheckPresentOptions; j++)
- {
- if (presentModes.IndexOf(presentOptions[j]) != UInt(-1))
- {
- m_presentMode = presentOptions[j];
- break;
- }
- }
-
- if (m_presentMode == VK_PRESENT_MODE_MAX_ENUM_KHR)
- {
- return SLANG_FAIL;
- }
- }
-
- VkSwapchainKHR oldSwapchain = VK_NULL_HANDLE;
-
- VkSwapchainCreateInfoKHR swapchainDesc = {};
- swapchainDesc.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
- swapchainDesc.surface = m_surface;
- swapchainDesc.minImageCount = 3;
- swapchainDesc.imageFormat = m_format;
- swapchainDesc.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
- swapchainDesc.imageExtent = imageExtent;
- swapchainDesc.imageArrayLayers = 1;
- swapchainDesc.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- swapchainDesc.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
- swapchainDesc.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
- swapchainDesc.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- swapchainDesc.presentMode = m_presentMode;
- swapchainDesc.clipped = VK_TRUE;
- swapchainDesc.oldSwapchain = oldSwapchain;
-
- SLANG_VK_RETURN_ON_FAIL(m_api->vkCreateSwapchainKHR(m_api->m_device, &swapchainDesc, nullptr, &m_swapChain));
-
- uint32_t numSwapChainImages = 0;
- m_api->vkGetSwapchainImagesKHR(m_api->m_device, m_swapChain, &numSwapChainImages, nullptr);
-
- {
- List<VkImage> images;
- images.SetSize(numSwapChainImages);
-
- m_api->vkGetSwapchainImagesKHR(m_api->m_device, m_swapChain, &numSwapChainImages, images.Buffer());
-
- m_images.SetSize(numSwapChainImages);
- for (int i = 0; i < int(numSwapChainImages); ++i)
- {
- Image& dstImage = m_images[i];
- dstImage.m_image = images[i];
-
- }
- }
-
- {
- VkImageViewCreateInfo createInfo = {};
- createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
-
- createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
- createInfo.format = m_format;
-
- createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
- createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
- createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
- createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
-
- createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- createInfo.subresourceRange.baseMipLevel = 0;
- createInfo.subresourceRange.levelCount = 1;
- createInfo.subresourceRange.baseArrayLayer = 0;
- createInfo.subresourceRange.layerCount = 1;
-
- for (int i = 0; i < int(numSwapChainImages); ++i)
- {
- Image& image = m_images[i];
-
- createInfo.image = image.m_image;
-
- SLANG_VK_RETURN_ON_FAIL(m_api->vkCreateImageView(m_api->m_device, &createInfo, nullptr, &image.m_imageView));
- }
- }
-
- if (m_renderPass != VK_NULL_HANDLE)
- {
- _createFrameBuffers(m_renderPass);
- }
-
- return SLANG_OK;
-}
-
-void VulkanSwapChain::_destroySwapChain()
-{
- if (!hasValidSwapChain())
- {
- return;
- }
-
- m_deviceQueue->waitForIdle();
-
- if (m_renderPass != VK_NULL_HANDLE)
- {
- _destroyFrameBuffers();
- }
-
- for (int i = 0; i < int(m_images.Count()); ++i)
- {
- Image& image = m_images[i];
-
- if (image.m_imageView != VK_NULL_HANDLE)
- {
- m_api->vkDestroyImageView(m_api->m_device, image.m_imageView, nullptr);
- }
- }
-
- if (m_swapChain != VK_NULL_HANDLE)
- {
- m_api->vkDestroySwapchainKHR(m_api->m_device, m_swapChain, nullptr);
- m_swapChain = VK_NULL_HANDLE;
- }
-
- // Mark that it is no longer used
- m_images.Clear();
-}
-
-VulkanSwapChain::~VulkanSwapChain()
-{
- _destroySwapChain();
-
- if (m_surface)
- {
- m_api->vkDestroySurfaceKHR(m_api->m_instance, m_surface, nullptr);
- m_surface = VK_NULL_HANDLE;
- }
-}
-
-int VulkanSwapChain::nextFrontImageIndex()
-{
- if (!hasValidSwapChain())
- {
- if (SLANG_FAILED(_createSwapChain()))
- {
- return -1;
- }
- }
-
- VkSemaphore beginFrameSemaphore = m_deviceQueue->makeCurrent(VulkanDeviceQueue::EventType::BeginFrame);
-
- uint32_t swapChainIndex = 0;
- VkResult result = m_api->vkAcquireNextImageKHR(m_api->m_device, m_swapChain, UINT64_MAX, beginFrameSemaphore, VK_NULL_HANDLE, &swapChainIndex);
-
- if (result != VK_SUCCESS)
- {
- _destroySwapChain();
- return -1;
- }
- m_currentSwapChainIndex = int(swapChainIndex);
- return swapChainIndex;
-}
-
-void VulkanSwapChain::present(bool vsync)
-{
- if (!hasValidSwapChain())
- {
- m_deviceQueue->flush();
- return;
- }
-
- VkSemaphore endFrameSemaphore = m_deviceQueue->makeCurrent(VulkanDeviceQueue::EventType::EndFrame);
-
- m_deviceQueue->flushStepA();
-
- uint32_t swapChainIndices[] = { uint32_t(m_currentSwapChainIndex) };
-
- VkPresentInfoKHR presentInfo = {};
- presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
- presentInfo.swapchainCount = 1;
- presentInfo.pSwapchains = &m_swapChain;
- presentInfo.pImageIndices = swapChainIndices;
- presentInfo.waitSemaphoreCount = 1;
- presentInfo.pWaitSemaphores = &endFrameSemaphore;
-
- VkResult result = m_api->vkQueuePresentKHR(m_deviceQueue->getQueue(), &presentInfo);
-
- m_deviceQueue->makeCompleted(VulkanDeviceQueue::EventType::EndFrame);
-
- m_deviceQueue->flushStepB();
-
- if (result != VK_SUCCESS || m_vsync != vsync)
- {
- m_vsync = vsync;
- _destroySwapChain();
- }
-}
-
-} // renderer_test
diff --git a/tools/render-test/vk-swap-chain.h b/tools/render-test/vk-swap-chain.h
deleted file mode 100644
index 2c9fb588d..000000000
--- a/tools/render-test/vk-swap-chain.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// vk-swap-chain.h
-#pragma once
-
-#include "vk-api.h"
-#include "vk-device-queue.h"
-
-#include "render.h"
-
-#include "../../source/core/list.h"
-
-namespace renderer_test {
-
-struct VulkanSwapChain
-{
- /* enum
- {
- kMaxImages = 8,
- }; */
-
- /// Base class for platform specific information
- struct PlatformDesc
- {
- };
-
-#if SLANG_WINDOWS_FAMILY
- struct WinPlatformDesc: public PlatformDesc
- {
- HINSTANCE m_hinstance;
- HWND m_hwnd;
- };
-#else
- struct XPlatformDesc : public PlatformDesc
- {
- Display* m_display;
- Window m_window;
- };
-#endif
-
- struct Desc
- {
- void init()
- {
- m_format = Format::Unknown;
- m_depthFormatTypeless = Format::Unknown;
- m_depthFormat = Format::Unknown;
- m_textureDepthFormat = Format::Unknown;
- }
-
- Format m_format;
- //bool m_enableFormat;
- Format m_depthFormatTypeless;
- Format m_depthFormat;
- Format m_textureDepthFormat;
- };
-
- struct Image
- {
- VkImage m_image = VK_NULL_HANDLE;
- VkImageView m_imageView = VK_NULL_HANDLE;
- VkFramebuffer m_frameBuffer = VK_NULL_HANDLE;
- };
-
-
- /// Must be called before the swap chain can be used
- SlangResult init(VulkanDeviceQueue* deviceQueue, const Desc& desc, const PlatformDesc* platformDesc);
-
- /// Create the frame buffers (they must be compatible with the supplied renderPass)
- SlangResult createFrameBuffers(VkRenderPass renderPass);
-
- /// Returned the desc used to construct the swap chain.
- /// Is invalid if init hasn't returned with successful result.
- const Desc& getDesc() const { return m_desc; }
-
- /// True if the swap chain is available
- bool hasValidSwapChain() const { return m_images.Count() > 0; }
-
- /// Present to the display
- void present(bool vsync);
-
- /// Get the current size of the window (in pixels written to widthOut, heightOut)
- void getWindowSize(int* widthOut, int* heightOut) const;
-
- /// Get the VkFormat for the back buffer
- VkFormat getVkFormat() const { return m_format; }
-
- /// Get width of the back buffers
- int getWidth() const { return m_width; }
- /// Get the height of the back buffer
- int getHeight() const { return m_height; }
-
- /// Get the detail about the images
- const Slang::List<Image>& getImages() const { return m_images; }
-
- /// Get the next front render image index. Returns -1, if image couldn't be found
- int nextFrontImageIndex();
-
- /// Dtor
- ~VulkanSwapChain();
-
- protected:
-
-
- template <typename T>
- void _setPlatformDesc(const T& desc)
- {
- const PlatformDesc* check = &desc;
- int size = (sizeof(T) + sizeof(void*) - 1) / sizeof(void*);
- m_platformDescBuffer.SetSize(size);
- *(T*)m_platformDescBuffer.Buffer() = desc;
- }
- template <typename T>
- const T* _getPlatformDesc() const { return static_cast<const T*>((const PlatformDesc*)m_platformDescBuffer.Buffer()); }
- SlangResult _createSwapChain();
- void _destroySwapChain();
- SlangResult _createFrameBuffers(VkRenderPass renderPass);
- void _destroyFrameBuffers();
-
- bool m_vsync = true;
- int m_width = 0;
- int m_height = 0;
-
- VkPresentModeKHR m_presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
- VkFormat m_format = VK_FORMAT_UNDEFINED; ///< The format used for backbuffer. Valid after successful init.
-
- VkSurfaceKHR m_surface = VK_NULL_HANDLE;
- VkSwapchainKHR m_swapChain = VK_NULL_HANDLE;
-
- VkRenderPass m_renderPass = VK_NULL_HANDLE; //< Not owned
-
- int m_currentSwapChainIndex = 0;
-
- Slang::List<Image> m_images;
-
- VulkanDeviceQueue* m_deviceQueue = nullptr;
- const VulkanApi* m_api = nullptr;
-
- Desc m_desc; ///< The desc used to init this swap chain
- Slang::List<void*> m_platformDescBuffer; ///< Buffer to hold the platform specific description parameters (as passed in platformDesc)
-};
-
-} // renderer_test
diff --git a/tools/render-test/vk-util.cpp b/tools/render-test/vk-util.cpp
deleted file mode 100644
index 925001144..000000000
--- a/tools/render-test/vk-util.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-// vk-util.cpp
-#include "vk-util.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-
-namespace renderer_test {
-
-/* static */VkFormat VulkanUtil::getVkFormat(Format format)
-{
- switch (format)
- {
- case Format::RGBA_Float32: return VK_FORMAT_R32G32B32A32_SFLOAT;
- case Format::RGB_Float32: return VK_FORMAT_R32G32B32_SFLOAT;
- case Format::RG_Float32: return VK_FORMAT_R32G32_SFLOAT;
- case Format::R_Float32: return VK_FORMAT_R32_SFLOAT;
- case Format::RGBA_Unorm_UInt8: return VK_FORMAT_R8G8B8A8_UNORM;
- case Format::R_UInt32: return VK_FORMAT_R32_UINT;
-
- case Format::D_Float32: return VK_FORMAT_D32_SFLOAT;
- case Format::D_Unorm24_S8: return VK_FORMAT_D24_UNORM_S8_UINT;
-
- default: return VK_FORMAT_UNDEFINED;
- }
-}
-
-/* static */SlangResult VulkanUtil::toSlangResult(VkResult res)
-{
- return (res == VK_SUCCESS) ? SLANG_OK : SLANG_FAIL;
-}
-
-/* static */Slang::Result VulkanUtil::handleFail(VkResult res)
-{
- if (res != VK_SUCCESS)
- {
- assert(!"Vulkan returned a failure");
- }
- return toSlangResult(res);
-}
-
-/* static */void VulkanUtil::checkFail(VkResult res)
-{
- assert(res != VK_SUCCESS);
- assert(!"Vulkan check failed");
-
-}
-
-/* static */VkPrimitiveTopology VulkanUtil::getVkPrimitiveTopology(PrimitiveTopology topology)
-{
- switch (topology)
- {
- case PrimitiveTopology::TriangleList: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
- default: break;
- }
- assert(!"Unknown topology");
- return VK_PRIMITIVE_TOPOLOGY_MAX_ENUM;
-}
-
-} // renderer_test
diff --git a/tools/render-test/vk-util.h b/tools/render-test/vk-util.h
deleted file mode 100644
index 2d98a1c0f..000000000
--- a/tools/render-test/vk-util.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// vk-util.h
-#pragma once
-
-#include "vk-api.h"
-#include "render.h"
-
-// Macros to make testing vulkan return codes simpler
-
-/// SLANG_VK_RETURN_ON_FAIL can be used in a similar way to SLANG_RETURN_ON_FAIL macro, except it will turn a vulkan failure into Slang::Result in the process
-/// Calls handleFail which on debug builds asserts
-#define SLANG_VK_RETURN_ON_FAIL(x) { VkResult _res = x; if (_res != VK_SUCCESS) { return VulkanUtil::handleFail(_res); } }
-
-#define SLANG_VK_RETURN_NULL_ON_FAIL(x) { VkResult _res = x; if (_res != VK_SUCCESS) { VulkanUtil::handleFail(_res); return nullptr; } }
-
-/// Is similar to SLANG_VK_RETURN_ON_FAIL, but does not return. Will call checkFail on failure - which asserts on debug builds.
-#define SLANG_VK_CHECK(x) { VkResult _res = x; if (_res != VK_SUCCESS) { VulkanUtil::checkFail(_res); } }
-
-namespace renderer_test {
-
-// Utility functions for Vulkan
-struct VulkanUtil
-{
- /// Get the equivalent VkFormat from the format
- /// Returns VK_FORMAT_UNDEFINED if a match is not found
- static VkFormat getVkFormat(Format format);
-
- /// Called by SLANG_VK_RETURN_FAIL if a res is a failure.
- /// On debug builds this will cause an assertion on failure.
- static Slang::Result handleFail(VkResult res);
- /// Called when a failure has occurred with SLANG_VK_CHECK - will typically assert.
- static void checkFail(VkResult res);
-
- /// Get the VkPrimitiveTopology for the given topology.
- /// Returns VK_PRIMITIVE_TOPOLOGY_MAX_ENUM on failure
- static VkPrimitiveTopology getVkPrimitiveTopology(PrimitiveTopology topology);
-
- /// Returns Slang::Result equivalent of a VkResult
- static Slang::Result toSlangResult(VkResult res);
-};
-
-} // renderer_test
diff --git a/tools/render-test/window.h b/tools/render-test/window.h
deleted file mode 100644
index 5d0a89ee4..000000000
--- a/tools/render-test/window.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// window.h
-#pragma once
-
-namespace renderer_test {
-
-typedef struct Window Window;
-
-Window* createWindow();
-
-} // renderer_test