1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
// vk-helper-functions.h
#pragma once
#include "core/slang-blob.h"
#include "vk-base.h"
#include "vk-util.h"
// Vulkan has a different coordinate system to ogl
// http://anki3d.org/vulkan-coordinate-system/
#ifdef _MSC_VER
#include <stddef.h>
#pragma warning(disable : 4996)
#if (_MSC_VER < 1900)
#define snprintf sprintf_s
#endif
#endif
#if SLANG_WINDOWS_FAMILY
#include <dxgi1_2.h>
#endif
namespace gfx
{
using namespace Slang;
namespace vk
{
// In order to bind shader parameters to the correct locations, we need to
// be able to describe those locations. Most shader parameters in Vulkan
// simply consume a single `binding`, but we also need to deal with
// parameters that represent push-constant ranges.
//
// In more complex cases we might be binding an entire "sub-object" like
// a parameter block, an entry point, etc. For the general case, we need
// to be able to represent a composite offset that includes offsets for
// each of the cases that Vulkan supports.
/// A "simple" binding offset that records `binding`, `set`, etc. offsets
struct SimpleBindingOffset
{
/// An offset in GLSL/SPIR-V `binding`s
uint32_t binding = 0;
/// The descriptor `set` that the `binding` field should be understood as an index into
uint32_t bindingSet = 0;
/// The offset in push-constant ranges (not bytes)
uint32_t pushConstantRange = 0;
/// Create a default (zero) offset
SimpleBindingOffset() {}
/// Create an offset based on offset information in the given Slang `varLayout`
SimpleBindingOffset(slang::VariableLayoutReflection* varLayout)
{
if (varLayout)
{
bindingSet = (uint32_t)varLayout->getBindingSpace(
SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT);
binding =
(uint32_t)varLayout->getOffset(SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT);
pushConstantRange =
(uint32_t)varLayout->getOffset(SLANG_PARAMETER_CATEGORY_PUSH_CONSTANT_BUFFER);
}
}
/// Add any values in the given `offset`
void operator+=(SimpleBindingOffset const& offset)
{
binding += offset.binding;
bindingSet += offset.bindingSet;
pushConstantRange += offset.pushConstantRange;
}
};
// While a "simple" binding offset representation will work in many cases,
// once we need to deal with layout for programs with interface-type parameters
// that have been statically specialized, we also need to track the offset
// for where to bind any "pending" data that arises from the process of static
// specialization.
//
// In order to conveniently track both the "primary" and "pending" offset information,
// we will define a more complete `BindingOffset` type that combines simple
// binding offsets for the primary and pending parts.
/// A representation of the offset at which to bind a shader parameter or sub-object
struct BindingOffset : SimpleBindingOffset
{
// Offsets for "primary" data are stored directly in the `BindingOffset`
// via the inheritance from `SimpleBindingOffset`.
/// Offset for any "pending" data
SimpleBindingOffset pending;
/// Create a default (zero) offset
BindingOffset() {}
/// Create an offset from a simple offset
explicit BindingOffset(SimpleBindingOffset const& offset)
: SimpleBindingOffset(offset)
{
}
/// Create an offset based on offset information in the given Slang `varLayout`
BindingOffset(slang::VariableLayoutReflection* varLayout)
: SimpleBindingOffset(varLayout), pending(varLayout->getPendingDataLayout())
{
}
/// Add any values in the given `offset`
void operator+=(SimpleBindingOffset const& offset) { SimpleBindingOffset::operator+=(offset); }
/// Add any values in the given `offset`
void operator+=(BindingOffset const& offset)
{
SimpleBindingOffset::operator+=(offset);
pending += offset.pending;
}
};
/// Context information required when binding shader objects to the pipeline
struct RootBindingContext
{
/// The pipeline layout being used for binding
VkPipelineLayout pipelineLayout;
/// An allocator to use for descriptor sets during binding
DescriptorSetAllocator* descriptorSetAllocator;
/// The device being used
DeviceImpl* device;
/// The descriptor sets that are being allocated and bound
List<VkDescriptorSet>* descriptorSets;
/// Information about all the push-constant ranges that should be bound
ConstArrayView<VkPushConstantRange> pushConstantRanges;
};
Size calcRowSize(Format format, int width);
GfxCount calcNumRows(Format format, int height);
VkAttachmentLoadOp translateLoadOp(IRenderPassLayout::TargetLoadOp loadOp);
VkAttachmentStoreOp translateStoreOp(IRenderPassLayout::TargetStoreOp storeOp);
VkPipelineCreateFlags translateRayTracingPipelineFlags(RayTracingPipelineFlags::Enum flags);
uint32_t getMipLevelSize(uint32_t mipLevel, uint32_t size);
VkImageLayout translateImageLayout(ResourceState state);
VkAccessFlagBits calcAccessFlags(ResourceState state);
VkPipelineStageFlagBits calcPipelineStageFlags(ResourceState state, bool src);
VkAccessFlags translateAccelerationStructureAccessFlag(AccessFlag access);
VkBufferUsageFlagBits _calcBufferUsageFlags(ResourceState state);
VkBufferUsageFlagBits _calcBufferUsageFlags(ResourceStateSet states);
VkImageUsageFlagBits _calcImageUsageFlags(ResourceState state);
VkImageViewType _calcImageViewType(ITextureResource::Type type, const ITextureResource::Desc& desc);
VkImageUsageFlagBits _calcImageUsageFlags(ResourceStateSet states);
VkImageUsageFlags _calcImageUsageFlags(
ResourceStateSet states,
MemoryType memoryType,
const void* initData);
VkAccessFlags calcAccessFlagsFromImageLayout(VkImageLayout layout);
VkPipelineStageFlags calcPipelineStageFlagsFromImageLayout(VkImageLayout layout);
VkImageAspectFlags getAspectMaskFromFormat(VkFormat format);
AdapterLUID getAdapterLUID(VulkanApi api, VkPhysicalDevice physicaDevice);
} // namespace vk
Result SLANG_MCALL getVKAdapters(List<AdapterInfo>& outAdapters);
Result SLANG_MCALL createVKDevice(const IDevice::Desc* desc, IDevice** outRenderer);
} // namespace gfx
|