summaryrefslogtreecommitdiffstats
path: root/tools/render-test
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-06-28 11:14:48 -0700
committerGitHub <noreply@github.com>2018-06-28 11:14:48 -0700
commitdfe13b54286b27dd15f591455bbb86b7798285c2 (patch)
tree4a11f01feaae059b6c11bdfbe12a614228af6dd5 /tools/render-test
parent22033f06573f900dc030c487b2c30feddf3d8f16 (diff)
Share graphics API layer between tests/examples (#603)
The `render-test` project has an in-progress graphics API abstraction layer, and it makes sense to share this code with our examples rather than write a bunch of redundant code between examples and tests. Most of this change is just moving files from `tools/render-test/*` to a new library project at `tools/slang-graphics/`. The most complicated code change there is renaming from `render_test` to `slang_graphics`. The existing `hello` example was ported to use the graphics API layer instead of raw D3D11 API calls. It is still hard-coded to use the D3D11 back-end and the `SLANG_DXBC` target, so more work is needed if we want to actually support multiple APIs in the examples. I also went ahead and implemented an extremely rudimentary set of APIs to abstract over the Windows platform calls that were being made in the example, so that we could potentially run that same example on other platforms. I did *not* port `render-test` to use those APIs, and I also did not implement them for anything but Windows (my assumption is that for most other platforms we would just use SDL2, and require people to ensure it is installed to their machine before building Slang examples).
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