Skip to content

Commit fbe6c1b

Browse files
committed
Incremental Improvements
1 parent 668b89b commit fbe6c1b

6 files changed

Lines changed: 124 additions & 43 deletions

File tree

projs/shadow/shadow-engine/core/src/core/job/Job.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ namespace SH::Jobs {
108108

109109
TaskGroup group { task, &context, 0, 0, 1, 0 };
110110

111-
if (queue.nThreads <= 1) {
111+
if (queue.nThreads < 1) {
112112
group.Execute();
113113
return;
114114
}
@@ -135,7 +135,7 @@ namespace SH::Jobs {
135135
group.groupIdx = grp * groups;
136136
group.groupEnd = std::min(group.groupIdx + groups, jobs);
137137

138-
if (queue.nThreads <= 1)
138+
if (queue.nThreads < 1)
139139
group.Execute();
140140
else
141141
queue.queues[queue.nextQueue.fetch_add(1) % queue.nThreads].Push(group);

projs/shadow/shadow-engine/renderer/base/inc/renderer/GraphicsDefine.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ namespace rx {
402402
CARTOON,
403403
UNLIT,
404404
WATER,
405+
INTERIOR,
405406
SIZE
406407
};
407408

@@ -1948,6 +1949,19 @@ namespace rx {
19481949
metaHolder(RaytracingPipelineMeta)
19491950
};
19501951

1952+
descriptor PipelineHash {
1953+
const PipelineState* pso = {};
1954+
size_t hash = {};
1955+
1956+
constexpr bool operator==(const PipelineHash& other) const {
1957+
return pso == other.pso && hash == other.hash;
1958+
}
1959+
1960+
constexpr size_t GetHash() const {
1961+
return ((size_t) pso & (hash << 1)) >> 1;
1962+
}
1963+
};
1964+
19511965
/**
19521966
* An easy way to reference entries in tables output by the Ray Tracing shaders.
19531967
*/
@@ -2521,3 +2535,10 @@ template<>
25212535
struct enable_bitmask_operators<rx::RenderPassFlags> {
25222536
static const bool enable = true;
25232537
};
2538+
2539+
template <>
2540+
struct hash<rx::PipelineHash> {
2541+
inline size_t operator()(const rx::PipelineHash& hash) const {
2542+
return hash.GetHash();
2543+
}
2544+
};

projs/shadow/shadow-engine/renderer/base/inc/renderer/Renderer.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,8 @@ namespace rx {
236236
static void DownsampleDepthBuffer(const Texture& dest, ThreadCommands cmd);
237237

238238
struct TiledLightResources {
239-
DirectX::XMUINT3 tileCount = {};
240-
GPUBuffer tileFrustums;
241-
GPUBuffer tilesOpaque;
242-
GPUBuffer tilesTransparent;
239+
DirectX::XMUINT2 tileCount = {};
240+
GPUBuffer entityTiles;
243241
};
244242

245243
static void CreateTiledLightResources(TiledLightResources& res, DirectX::XMUINT2 resolution);

projs/shadow/shadow-engine/renderer/base/inc/renderer/interfaces/VulkanInterface.h

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include <vulkan/vulkan.h>
55
#include "vk_mem_alloc.h"
66
#include "shadow/util/Synchronization.h"
7-
#include <atomic>
87
#include <deque>
98
#include <mutex>
109

@@ -48,6 +47,8 @@ namespace rx {
4847
VkPhysicalDeviceMeshShaderPropertiesEXT meshShaderProps = {}; // Properties of the physical device's support for mesh shaders.
4948
VkPhysicalDeviceMemoryProperties2 memoryProps = {}; // Properties of the physical device's graphics memory
5049
VkPhysicalDeviceDepthStencilResolveProperties depthStencilResolveProps = {}; // Properties of the physical device's support for depth stenciling.
50+
VkPhysicalDeviceConservativeRasterizationPropertiesEXT conservativeRasterProps = {}; // Properties of the physical device's support for conservative
51+
bool useConservativeRasterization = false; // Whether Conservative Rasterization is used in the currently active physical device.
5152
VkPhysicalDeviceFeatures2 deviceFeatures2 = {}; // Optional Vulkan features that the physical device supports.
5253
VkPhysicalDeviceVulkan11Features deviceFeatures11 = {}; // Optional Vulkan 1.1 features that the physical device supports.
5354
VkPhysicalDeviceVulkan12Features deviceFeatures12 = {}; // Optional Vulkan 1.2 features that the physical device supports.
@@ -301,12 +302,13 @@ namespace rx {
301302
DescriptorPool bindPools[frameBuffers]; // The DescriptorBindPools for this thread, for each frame
302303
GPULinearAllocator frameAllocators[frameBuffers]; // The linear allocators for each frame
303304

304-
std::vector<std::pair<size_t, VkPipeline>> pipelines; // A vectorized map of pipeline hash to PSO
305+
306+
std::vector<std::pair<PipelineHash, VkPipeline>> pipelines; // A vectorized map of pipeline hash to PSO
305307
const PipelineState* activePSO = nullptr; // The active PSO
306308
const Shader* activeShader = nullptr; // The active (bound) shader - render or compute.
307309
const RaytracingPipeline* activeRT = nullptr; // The active RayTracing acceleration structure (bounding volume hierarchy)
308310

309-
size_t prevPipelineHash = 0; // The hash of the pipeline that was previously bound to the current thread - for use with the vectorized map
311+
PipelineHash prevPipelineHash = {}; // The hash of the pipeline that was previously bound to the current thread - for use with the vectorized map
310312
ShadingRate prevShadeRate = {}; // The Shading Rate that was previously bound to the current thread - for easy comparison
311313
std::vector<SwapChain> prevSwapchains; // All Swap-Chains that were previously bound to the current thread.
312314
bool PSODirty = false; // Whether the Pipeline State Object has changed in a way that requires some form of re-initialization
@@ -334,7 +336,7 @@ namespace rx {
334336
bindPools[bufIdx].Reset();
335337
binds.Reset();
336338
frameAllocators[bufIdx].Reset();
337-
prevPipelineHash = 0;
339+
prevPipelineHash = {};
338340
activePSO = nullptr;
339341
activeShader = nullptr;
340342
activeRT = nullptr;
@@ -361,8 +363,8 @@ namespace rx {
361363
}
362364
};
363365

364-
std::vector<std::unique_ptr<VulkanThreadCommands>> cmds; // A list of all active and inactive Thread Commands, for all threads managed by the engine.
365-
uint32_t cmdCount = 0; // The number of active Thread Commands. Should always be == cmds.size(), unless a thread is currently initializing one.
366+
std::vector<std::unique_ptr<VulkanThreadCommands>> cmds; // A list of all active and inactive Thread Commands, for all threads managed by the engine.
367+
uint32_t cmdCount = 0; // The number of active Thread Commands. Should always be == cmds.size(), unless a thread is currently initializing one.
366368
SH::SpinLock cmdLock; // A lock to prevent more than one thread submitting the commands at a time.
367369

368370
/**
@@ -384,11 +386,11 @@ namespace rx {
384386
uint32_t firstBindless = 0;
385387
};
386388

387-
mutable std::unordered_map<size_t, PSOLayout> PSOcache; // A cache of all created Pipeline State Objects indexed by hash, for easy switching.
389+
mutable std::unordered_map<PipelineHash, PSOLayout> PSOcache; // A cache of all created Pipeline State Objects indexed by hash, for easy switching.
388390
mutable std::mutex PSOcacheMutex; // A lock to prevent the PSO cache being modified during access.
389391

390392
VkPipelineCache pipelineCache = VK_NULL_HANDLE; // A Vulkan Pipeline Cache. Saves to disk for reuse, preventing long initialization times every startup.
391-
std::unordered_map<size_t, VkPipeline> pipelines; // A cache of VkPipeline objects (not Pipeline State Objects, see PSOcache for that)
393+
std::unordered_map<PipelineHash, VkPipeline> pipelines; // A cache of VkPipeline objects (not Pipeline State Objects, see PSOcache for that)
392394

393395
/**
394396
* @brief Verify that all PSOs in the cache are valid.
@@ -440,7 +442,7 @@ namespace rx {
440442
std::vector<int> freeList;
441443
std::mutex lock;
442444

443-
void Init(VkDevice device, VkDescriptorType type, uint32_t descriptors) {
445+
void Init(VulkanInterface* device, VkDescriptorType type, uint32_t descriptors) {
444446
descriptors = std::min(descriptors, 500'000u);
445447

446448
VkDescriptorPoolSize size = {
@@ -456,7 +458,7 @@ namespace rx {
456458
.pPoolSizes = &size,
457459
};
458460

459-
VkResult res = vkCreateDescriptorPool(device, &create, nullptr, &pool);
461+
VkResult res = vkCreateDescriptorPool(device->device, &create, nullptr, &pool);
460462
assert(res == VK_SUCCESS);
461463

462464
VkDescriptorSetLayoutBinding binding = {
@@ -484,7 +486,7 @@ namespace rx {
484486
.pBindings = &binding,
485487
};
486488

487-
res = vkCreateDescriptorSetLayout(device, &layoutCreate, nullptr, &setLayout);
489+
res = vkCreateDescriptorSetLayout(device->device, &layoutCreate, nullptr, &setLayout);
488490
assert(res == VK_SUCCESS);
489491

490492
VkDescriptorSetAllocateInfo allocateInfo = {
@@ -494,11 +496,56 @@ namespace rx {
494496
.pSetLayouts = &setLayout
495497
};
496498

497-
res = vkAllocateDescriptorSets(device, &allocateInfo, &set);
499+
res = vkAllocateDescriptorSets(device->device, &allocateInfo, &set);
498500
assert(res == VK_SUCCESS);
499501

500502
for (int i = 0; i < (int)descriptors; i++)
501503
freeList.push_back((int)descriptors - i - 1);
504+
505+
if (type != VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) {
506+
// We do a little memory leaking
507+
// Shader compiler might be dodgy, so we add safety buffers to prevent null pointers in all possible edge cases
508+
int idx = Allocate();
509+
VkWriteDescriptorSet write = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET};
510+
write.descriptorType = type;
511+
write.dstBinding = 0;
512+
write.dstArrayElement = idx;
513+
write.descriptorCount = 1;
514+
write.dstSet = set;
515+
516+
VkDescriptorImageInfo imageInfo = {};
517+
VkDescriptorBufferInfo bufferInfo = {};
518+
519+
switch (type) {
520+
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
521+
imageInfo.imageView = device->nullImageView2;
522+
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
523+
write.pImageInfo = &imageInfo;
524+
break;
525+
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
526+
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
527+
write.pTexelBufferView = &device->nullBufferView;
528+
break;
529+
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
530+
bufferInfo = { device->nullBuffer, VK_WHOLE_SIZE };
531+
write.pBufferInfo = &bufferInfo;
532+
break;
533+
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
534+
imageInfo.imageView = device->nullImageView2;
535+
imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
536+
write.pImageInfo = &imageInfo;
537+
break;
538+
case VK_DESCRIPTOR_TYPE_SAMPLER:
539+
imageInfo.sampler = device->nullSampler;
540+
write.pImageInfo = &imageInfo;
541+
break;
542+
default:
543+
assert("Descriptor error in bindless heap: non acceleration structure descriptor type with non zero index");
544+
break;
545+
}
546+
547+
vkUpdateDescriptorSets(device->device, 1, &write, 0, nullptr);
548+
}
502549
}
503550

504551
void Destroy(VkDevice device) {
@@ -917,12 +964,19 @@ y; \
917964

918965
RenderPassMeta GetRenderPassMeta(ThreadCommands cmd) override {
919966
return GetThreadCommands(cmd).passMeta;
920-
};
967+
}
921968

922969
// Get the allocator to be used for the current frame.
923970
GPULinearAllocator& GetAllocator(ThreadCommands cmd) override {
924971
return GetThreadCommands(cmd).frameAllocators[GetBufferIndex()];
925-
};
972+
}
973+
974+
VkDevice GetDevice();
975+
VkPhysicalDevice GetPhysicalDevice();
976+
VkInstance GetInstance();
977+
VkQueue GetGraphicsQueue();
978+
uint32_t GetGraphicsIndex();
979+
VkImage GetTextureInternal(const rx::Texture* tex);
926980

927981
};
928982
}

projs/shadow/shadow-engine/renderer/base/src/renderer/Renderer.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -123,34 +123,31 @@ namespace rx::internal {
123123

124124
std::vector<uint8_t> debugTexts; // A buffer of texts used to send data to the console from the renderer.
125125

126-
SH::SpinLock mipperLock; // A lock used by the dynamic mipmap generator.
126+
SH::SpinLock mipperLock; // A lock used by the dynamic mipmap generator.
127127
std::vector<std::pair<Texture, bool>> mipperList; // A list of textures for the dynamic mipmap generator to process. pair<Texture, whether it has been processed yet>
128128
std::vector<std::pair<Texture, Texture>> decompressorList; // A list of textures for the decompressor to work on. pair<compressed texture, decompressed texture>
129129

130-
GPUBuffer luminanceBuffer; // A buffer for dynamic luminance compensation. Required by some shaders to exist. NVIDIA 10xx GPUs will error without such.
131-
132-
SH::Jobs::ExecutionContext pipelineJobContext[ENUMSIZE(defs::RenderPass)]; // Job contexts for processing PSOs.
130+
SH::Jobs::ExecutionContext pipelineJobContext[ENUMSIZE(defs::RenderPass)]; // Job contexts for processing PSOs.
133131

134132
PipelineState PSOOcclusion; // PSO for Occlusion Queries
135-
PipelineState PSOBillboard[ENUMSIZE(defs::RenderPass)]; // PSO for billboard rendering, per render pass
133+
PipelineState PSOBillboard[ENUMSIZE(defs::RenderPass)]; // PSO for billboard rendering, per render pass
136134
PipelineState PSOBillboardWire; // PSO for billboard rendering of wires and lines.
137135
PipelineState PSOGatherBillboard; // PSO for capturing billboard-rendered pixels into a buffer
138-
PipelineState PSOLightVisual[ENUMSIZE(defs::LightType)]; // PSO for visualizing light-affected pixels into a buffer
139-
PipelineState PSOLightVolumetric[ENUMSIZE(defs::LightType)]; // PSO for rendering volumetric lights
136+
PipelineState PSOLightVisual[ENUMSIZE(defs::LightType)]; // PSO for visualizing light-affected pixels into a buffer
137+
PipelineState PSOLightVolumetric[ENUMSIZE(defs::LightType)]; // PSO for rendering volumetric lights
140138
PipelineState PSOLightmap; // PSO for rendering light maps
141139
PipelineState PSOLensFlare; // PSO for rendering lens flares
142140
PipelineState PSODownsampleDepth; // PSO for downsampling depth buffers
143141
PipelineState PSOUpsample; // PSO for bilateral upsampling
144142
PipelineState PSOUpsampleClouds; // PSO for upsampling volumetric clouds
145143
PipelineState PSOOutline; // PSO for rendering outlines of objects
146-
PipelineState PSOSky[ENUMSIZE(defs::SkyRenderType)]; // PSO for sky rendering, per type
147-
PipelineState PSODebug[ENUMSIZE(defs::DebugRenderType)]; // PSO for debug rendering, per mode
144+
PipelineState PSOSky[ENUMSIZE(defs::SkyRenderType)]; // PSO for sky rendering, per type
145+
PipelineState PSODebug[ENUMSIZE(defs::DebugRenderType)]; // PSO for debug rendering, per mode
148146
PipelineState PSOWire; // PSO for wire (thin strips of pixels) rendering
149147
PipelineState PSOWireTess; // PSO for wire (thin strips of pixels) rendering, with tesselation
150148

151149
RaytracingPipeline PSORTReflect; // PSO for ray-traced reflections
152150

153-
154151
/**
155152
* An instance of a mesh, with associated distance to the camera.
156153
* Can be sorted back-to-front or front-to-back depending on need.
@@ -247,13 +244,13 @@ namespace rx::internal {
247244
* Use as an index into the array of pipeline state objects.
248245
*/
249246
union RenderVariants {
250-
struct __attribute__((packed)) { uint8_t pass : 4; uint8_t shader; uint8_t blend : 4; uint8_t cull : 2; uint8_t tesselation : 1; uint8_t alpha : 1; uint32_t sample : 4; } parts;
247+
struct __attribute__((packed)) { uint8_t pass : 4; uint8_t shader; uint8_t blend : 4; uint8_t cull : 2; uint8_t tesselation : 1; uint8_t alpha : 1; uint32_t sample : 4; uint8_t mesh : 1;} parts;
251248
uint32_t data;
252249
};
253250

254-
std::unordered_map<uint32_t, PipelineState> PSOByVariant[ENUMSIZE(defs::RenderPass)][ENUMSIZE(defs::MaterialShaderType)]; // TODO: Material Component types
251+
std::unordered_map<uint32_t, PipelineState> PSOByVariant[ENUMSIZE(defs::RenderPass)][ENUMSIZE(defs::MaterialShaderType)][2];
255252
inline PipelineState* GetPipelineForVariants(RenderVariants var) {
256-
return &PSOByVariant[var.parts.pass][var.parts.shader][var.data];
253+
return &PSOByVariant[var.parts.pass][var.parts.shader][var.parts.mesh][var.data];
257254
}
258255

259256
defs::ShaderType VertexShaderFor(defs::RenderPass pass, bool tesselation, bool alpha, bool transparent) {

0 commit comments

Comments
 (0)