Skip to content

Commit

Permalink
Pipeline hashing simplification and hash collision handling (#1045)
Browse files Browse the repository at this point in the history
  • Loading branch information
turanszkij authored Jan 24, 2025
1 parent 7161d98 commit f030147
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 56 deletions.
27 changes: 27 additions & 0 deletions WickedEngine/wiGraphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,21 @@ namespace wi::graphics
constexpr const RaytracingPipelineStateDesc& GetDesc() const { return desc; }
};

struct PipelineHash
{
const PipelineState* pso = nullptr;
uint64_t renderpass_hash = 0;

constexpr bool operator==(const PipelineHash& other) const
{
return (pso == other.pso) && (renderpass_hash == other.renderpass_hash);
}
constexpr uint64_t get_hash() const
{
return (uint64_t(pso) ^ (renderpass_hash << 1)) >> 1;
}
};

struct ShaderTable
{
const GPUBuffer* buffer = nullptr;
Expand Down Expand Up @@ -2107,3 +2122,15 @@ template<>
struct enable_bitmask_operators<wi::graphics::RenderPassFlags> {
static const bool enable = true;
};

namespace std
{
template <>
struct hash<wi::graphics::PipelineHash>
{
inline uint64_t operator()(const wi::graphics::PipelineHash& hash) const
{
return hash.get_hash();
}
};
}
32 changes: 7 additions & 25 deletions WickedEngine/wiGraphicsDevice_DX12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1422,7 +1422,6 @@ namespace dx12_internal
std::shared_ptr<GraphicsDevice_DX12::AllocationHandler> allocationhandler;
ComPtr<ID3D12PipelineState> resource;
ComPtr<ID3D12RootSignature> rootSignature;
size_t hash = 0;

wi::vector<uint8_t> shadercode;
wi::vector<D3D12_INPUT_ELEMENT_DESC> input_elements;
Expand Down Expand Up @@ -2089,7 +2088,7 @@ std::mutex queue_locker;
return;

const PipelineState* pso = commandlist.active_pso;
size_t pipeline_hash = commandlist.prev_pipeline_hash;
PipelineHash pipeline_hash = commandlist.prev_pipeline_hash;

auto internal_state = to_internal(pso);

Expand Down Expand Up @@ -3841,7 +3840,6 @@ std::mutex queue_locker;
shader->internal_state = internal_state;

internal_state->shadercode.resize(shadercode_size);
internal_state->hash = 0;
std::memcpy(internal_state->shadercode.data(), shadercode, shadercode_size);
shader->stage = stage;

Expand Down Expand Up @@ -3975,21 +3973,6 @@ std::mutex queue_locker;

pso->desc = *desc;

internal_state->hash = 0;
wi::helper::hash_combine(internal_state->hash, desc->ms);
wi::helper::hash_combine(internal_state->hash, desc->as);
wi::helper::hash_combine(internal_state->hash, desc->vs);
wi::helper::hash_combine(internal_state->hash, desc->ps);
wi::helper::hash_combine(internal_state->hash, desc->hs);
wi::helper::hash_combine(internal_state->hash, desc->ds);
wi::helper::hash_combine(internal_state->hash, desc->gs);
wi::helper::hash_combine(internal_state->hash, desc->il);
wi::helper::hash_combine(internal_state->hash, desc->rs);
wi::helper::hash_combine(internal_state->hash, desc->bs);
wi::helper::hash_combine(internal_state->hash, desc->dss);
wi::helper::hash_combine(internal_state->hash, desc->pt);
wi::helper::hash_combine(internal_state->hash, desc->sample_mask);

auto& stream = internal_state->stream;
if (pso->desc.vs != nullptr)
{
Expand Down Expand Up @@ -4186,7 +4169,6 @@ std::mutex queue_locker;

if (renderpass_info != nullptr)
{
wi::helper::hash_combine(internal_state->hash, renderpass_info->get_hash());
DXGI_FORMAT DSFormat = _ConvertFormat(renderpass_info->ds_format);
D3D12_RT_FORMAT_ARRAY formats = {};
formats.NumRenderTargets = renderpass_info->rt_count;
Expand Down Expand Up @@ -6629,14 +6611,14 @@ std::mutex queue_locker;
}
}

commandlist.prev_pipeline_hash = 0;
commandlist.prev_pipeline_hash = {};
commandlist.dirty_pso = false;
}
else
{
size_t pipeline_hash = 0;
wi::helper::hash_combine(pipeline_hash, internal_state->hash);
wi::helper::hash_combine(pipeline_hash, commandlist.renderpass_info.get_hash());
PipelineHash pipeline_hash;
pipeline_hash.pso = pso;
pipeline_hash.renderpass_hash = commandlist.renderpass_info.get_hash();
if (commandlist.prev_pipeline_hash == pipeline_hash)
{
return;
Expand Down Expand Up @@ -6669,7 +6651,7 @@ std::mutex queue_locker;

assert(cs->stage == ShaderStage::CS || cs->stage == ShaderStage::LIB);

commandlist.prev_pipeline_hash = 0;
commandlist.prev_pipeline_hash = {};

commandlist.active_cs = cs;

Expand Down Expand Up @@ -7205,7 +7187,7 @@ std::mutex queue_locker;
CommandList_DX12& commandlist = GetCommandList(cmd);
commandlist.active_cs = nullptr;
commandlist.active_pso = nullptr;
commandlist.prev_pipeline_hash = 0;
commandlist.prev_pipeline_hash = {};
commandlist.active_rt = rtpso;

BindComputeShader(rtpso->desc.shader_libraries.front().shader, cmd);
Expand Down
8 changes: 4 additions & 4 deletions WickedEngine/wiGraphicsDevice_DX12.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ namespace wi::graphics
};
wi::vector<Discard> discards;
D3D_PRIMITIVE_TOPOLOGY prev_pt = {};
wi::vector<std::pair<size_t, Microsoft::WRL::ComPtr<ID3D12PipelineState>>> pipelines_worker;
size_t prev_pipeline_hash = {};
wi::vector<std::pair<PipelineHash, Microsoft::WRL::ComPtr<ID3D12PipelineState>>> pipelines_worker;
PipelineHash prev_pipeline_hash = {};
const PipelineState* active_pso = {};
const Shader* active_cs = {};
const RaytracingPipelineState* active_rt = {};
Expand Down Expand Up @@ -213,7 +213,7 @@ namespace wi::graphics
binder.reset();
frame_allocators[buffer_index].reset();
prev_pt = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
prev_pipeline_hash = 0;
prev_pipeline_hash = {};
active_pso = nullptr;
active_cs = nullptr;
active_rt = nullptr;
Expand Down Expand Up @@ -272,7 +272,7 @@ namespace wi::graphics
return *(CommandList_DX12*)cmd.internal_state;
}

wi::unordered_map<size_t, Microsoft::WRL::ComPtr<ID3D12PipelineState>> pipelines_global;
wi::unordered_map<PipelineHash, Microsoft::WRL::ComPtr<ID3D12PipelineState>> pipelines_global;

void pso_validate(CommandList cmd);

Expand Down
28 changes: 6 additions & 22 deletions WickedEngine/wiGraphicsDevice_Vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -922,7 +922,6 @@ namespace vulkan_internal
VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE; // no lifetime management here
wi::vector<VkDescriptorSetLayoutBinding> layoutBindings;
wi::vector<VkImageViewType> imageViewTypes;
size_t hash = 0;

wi::vector<BindingUsage> bindlessBindings;
wi::vector<VkDescriptorSet> bindlessSets;
Expand Down Expand Up @@ -2130,7 +2129,7 @@ using namespace vulkan_internal;
return;

const PipelineState* pso = commandlist.active_pso;
size_t pipeline_hash = commandlist.prev_pipeline_hash;
PipelineHash pipeline_hash = commandlist.prev_pipeline_hash;
auto internal_state = to_internal(pso);

VkPipeline pipeline = VK_NULL_HANDLE;
Expand Down Expand Up @@ -5170,21 +5169,6 @@ using namespace vulkan_internal;
pso->internal_state = internal_state;
pso->desc = *desc;

internal_state->hash = 0;
wi::helper::hash_combine(internal_state->hash, desc->ms);
wi::helper::hash_combine(internal_state->hash, desc->as);
wi::helper::hash_combine(internal_state->hash, desc->vs);
wi::helper::hash_combine(internal_state->hash, desc->ps);
wi::helper::hash_combine(internal_state->hash, desc->hs);
wi::helper::hash_combine(internal_state->hash, desc->ds);
wi::helper::hash_combine(internal_state->hash, desc->gs);
wi::helper::hash_combine(internal_state->hash, desc->il);
wi::helper::hash_combine(internal_state->hash, desc->rs);
wi::helper::hash_combine(internal_state->hash, desc->bs);
wi::helper::hash_combine(internal_state->hash, desc->dss);
wi::helper::hash_combine(internal_state->hash, desc->pt);
wi::helper::hash_combine(internal_state->hash, desc->sample_mask);

VkResult res = VK_SUCCESS;

{
Expand Down Expand Up @@ -8172,14 +8156,14 @@ using namespace vulkan_internal;
vkCmdBindPipeline(commandlist.GetCommandBuffer(), VK_PIPELINE_BIND_POINT_GRAPHICS, internal_state->pipeline);
}

commandlist.prev_pipeline_hash = 0;
commandlist.prev_pipeline_hash = {};
commandlist.dirty_pso = false;
}
else
{
size_t pipeline_hash = 0;
wi::helper::hash_combine(pipeline_hash, internal_state->hash);
wi::helper::hash_combine(pipeline_hash, commandlist.renderpass_info.get_hash());
PipelineHash pipeline_hash;
pipeline_hash.pso = pso;
pipeline_hash.renderpass_hash = commandlist.renderpass_info.get_hash();
if (commandlist.prev_pipeline_hash == pipeline_hash)
{
commandlist.active_pso = pso;
Expand Down Expand Up @@ -8956,7 +8940,7 @@ using namespace vulkan_internal;
void GraphicsDevice_Vulkan::BindRaytracingPipelineState(const RaytracingPipelineState* rtpso, CommandList cmd)
{
CommandList_Vulkan& commandlist = GetCommandList(cmd);
commandlist.prev_pipeline_hash = 0;
commandlist.prev_pipeline_hash = {};
commandlist.active_rt = rtpso;

BindComputeShader(rtpso->desc.shader_libraries.front().shader, cmd);
Expand Down
8 changes: 4 additions & 4 deletions WickedEngine/wiGraphicsDevice_Vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ namespace wi::graphics
DescriptorBinderPool binder_pools[BUFFERCOUNT];
GPULinearAllocator frame_allocators[BUFFERCOUNT];

wi::vector<std::pair<size_t, VkPipeline>> pipelines_worker;
size_t prev_pipeline_hash = {};
wi::vector<std::pair<PipelineHash, VkPipeline>> pipelines_worker;
PipelineHash prev_pipeline_hash = {};
const PipelineState* active_pso = {};
const Shader* active_cs = {};
const RaytracingPipelineState* active_rt = {};
Expand All @@ -265,7 +265,7 @@ namespace wi::graphics
binder_pools[buffer_index].reset();
binder.reset();
frame_allocators[buffer_index].reset();
prev_pipeline_hash = 0;
prev_pipeline_hash = {};
active_pso = nullptr;
active_cs = nullptr;
active_rt = nullptr;
Expand Down Expand Up @@ -307,7 +307,7 @@ namespace wi::graphics
mutable std::mutex pso_layout_cache_mutex;

VkPipelineCache pipelineCache = VK_NULL_HANDLE;
wi::unordered_map<size_t, VkPipeline> pipelines_global;
wi::unordered_map<PipelineHash, VkPipeline> pipelines_global;

void pso_validate(CommandList cmd);

Expand Down
2 changes: 1 addition & 1 deletion WickedEngine/wiVersion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace wi::version
// minor features, major updates, breaking compatibility changes
const int minor = 71;
// minor bug fixes, alterations, refactors, updates
const int revision = 663;
const int revision = 664;

const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);

Expand Down

0 comments on commit f030147

Please sign in to comment.