2018-03-29 12:06:53 +02:00
|
|
|
#include <chrono>
|
2018-02-14 17:54:35 +01:00
|
|
|
#include <cstring>
|
|
|
|
|
2017-10-13 03:19:23 +02:00
|
|
|
#include "dxvk_compute.h"
|
2018-01-16 15:00:19 +01:00
|
|
|
#include "dxvk_device.h"
|
2017-10-13 03:19:23 +02:00
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
2018-02-14 17:54:35 +01:00
|
|
|
bool DxvkComputePipelineStateInfo::operator == (const DxvkComputePipelineStateInfo& other) const {
|
|
|
|
return std::memcmp(this, &other, sizeof(DxvkComputePipelineStateInfo)) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool DxvkComputePipelineStateInfo::operator != (const DxvkComputePipelineStateInfo& other) const {
|
|
|
|
return std::memcmp(this, &other, sizeof(DxvkComputePipelineStateInfo)) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-13 03:19:23 +02:00
|
|
|
DxvkComputePipeline::DxvkComputePipeline(
|
2018-01-16 15:00:19 +01:00
|
|
|
const DxvkDevice* device,
|
2018-01-13 22:18:32 +01:00
|
|
|
const Rc<DxvkPipelineCache>& cache,
|
|
|
|
const Rc<DxvkShader>& cs)
|
2018-01-16 15:00:19 +01:00
|
|
|
: m_device(device), m_vkd(device->vkd()),
|
|
|
|
m_cache(cache) {
|
2017-12-07 09:38:31 +01:00
|
|
|
DxvkDescriptorSlotMapping slotMapping;
|
|
|
|
cs->defineResourceSlots(slotMapping);
|
|
|
|
|
2018-01-23 17:40:36 +01:00
|
|
|
m_layout = new DxvkPipelineLayout(m_vkd,
|
2017-12-07 09:38:31 +01:00
|
|
|
slotMapping.bindingCount(),
|
2018-03-17 23:50:03 +01:00
|
|
|
slotMapping.bindingInfos(),
|
|
|
|
VK_PIPELINE_BIND_POINT_COMPUTE);
|
2017-12-07 09:38:31 +01:00
|
|
|
|
2018-01-16 15:00:19 +01:00
|
|
|
m_cs = cs->createShaderModule(m_vkd, slotMapping);
|
2017-12-07 09:38:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DxvkComputePipeline::~DxvkComputePipeline() {
|
2018-03-16 01:24:03 +01:00
|
|
|
this->destroyPipelines();
|
2017-12-07 09:38:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-02-14 17:54:35 +01:00
|
|
|
VkPipeline DxvkComputePipeline::getPipelineHandle(
|
2018-03-16 01:24:03 +01:00
|
|
|
const DxvkComputePipelineStateInfo& state) {
|
|
|
|
|
|
|
|
for (const PipelineStruct& pair : m_pipelines) {
|
|
|
|
if (pair.stateVector == state)
|
|
|
|
return pair.pipeline;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkPipeline pipeline = this->compilePipeline(state, m_basePipeline);
|
|
|
|
m_pipelines.push_back({ state, pipeline });
|
|
|
|
|
|
|
|
if (m_basePipeline == VK_NULL_HANDLE)
|
|
|
|
m_basePipeline = pipeline;
|
|
|
|
return pipeline;
|
2018-02-14 17:54:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-16 01:24:03 +01:00
|
|
|
VkPipeline DxvkComputePipeline::compilePipeline(
|
|
|
|
const DxvkComputePipelineStateInfo& state,
|
|
|
|
VkPipeline baseHandle) const {
|
2017-10-14 23:52:47 +02:00
|
|
|
std::vector<VkDescriptorSetLayoutBinding> bindings;
|
2018-03-02 02:33:06 -07:00
|
|
|
|
|
|
|
if (Logger::logLevel() <= LogLevel::Debug) {
|
|
|
|
Logger::debug("Compiling compute pipeline...");
|
|
|
|
Logger::debug(str::format(" cs : ", m_cs ->debugName()));
|
|
|
|
}
|
2017-10-14 23:52:47 +02:00
|
|
|
|
2018-03-16 01:24:03 +01:00
|
|
|
std::array<VkBool32, MaxNumActiveBindings> specData;
|
|
|
|
std::array<VkSpecializationMapEntry, MaxNumActiveBindings> specMap;
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < MaxNumActiveBindings; i++) {
|
|
|
|
specData[i] = state.bsBindingState.isBound(i) ? VK_TRUE : VK_FALSE;
|
|
|
|
specMap [i] = { i, static_cast<uint32_t>(sizeof(VkBool32)) * i, sizeof(VkBool32) };
|
|
|
|
}
|
|
|
|
|
|
|
|
VkSpecializationInfo specInfo;
|
|
|
|
specInfo.mapEntryCount = specMap.size();
|
|
|
|
specInfo.pMapEntries = specMap.data();
|
|
|
|
specInfo.dataSize = specData.size() * sizeof(VkBool32);
|
|
|
|
specInfo.pData = specData.data();
|
|
|
|
|
2017-10-14 23:52:47 +02:00
|
|
|
VkComputePipelineCreateInfo info;
|
|
|
|
info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
|
|
|
info.pNext = nullptr;
|
2018-03-16 01:24:03 +01:00
|
|
|
info.flags = baseHandle == VK_NULL_HANDLE
|
|
|
|
? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT
|
|
|
|
: VK_PIPELINE_CREATE_DERIVATIVE_BIT;
|
|
|
|
info.stage = m_cs->stageInfo(&specInfo);
|
2017-12-03 20:23:26 +01:00
|
|
|
info.layout = m_layout->pipelineLayout();
|
2018-03-16 01:24:03 +01:00
|
|
|
info.basePipelineHandle = baseHandle;
|
2018-01-10 22:54:00 +01:00
|
|
|
info.basePipelineIndex = -1;
|
2017-10-14 23:52:47 +02:00
|
|
|
|
2018-03-29 12:06:53 +02:00
|
|
|
// Time pipeline compilation for debugging purposes
|
|
|
|
auto t0 = std::chrono::high_resolution_clock::now();
|
|
|
|
|
2018-03-16 01:24:03 +01:00
|
|
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
2017-10-14 23:52:47 +02:00
|
|
|
if (m_vkd->vkCreateComputePipelines(m_vkd->device(),
|
2018-03-16 01:24:03 +01:00
|
|
|
m_cache->handle(), 1, &info, nullptr, &pipeline) != VK_SUCCESS) {
|
2018-01-31 00:48:39 +01:00
|
|
|
Logger::err("DxvkComputePipeline: Failed to compile pipeline");
|
2018-04-02 19:05:41 +02:00
|
|
|
Logger::err(str::format(" cs : ", m_cs ->debugName()));
|
2018-03-16 01:24:03 +01:00
|
|
|
return VK_NULL_HANDLE;
|
|
|
|
}
|
|
|
|
|
2018-03-29 12:06:53 +02:00
|
|
|
auto t1 = std::chrono::high_resolution_clock::now();
|
|
|
|
auto td = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0);
|
|
|
|
Logger::debug(str::format("DxvkComputePipeline: Finished in ", td.count(), " ms"));
|
|
|
|
|
2018-03-21 02:45:11 +01:00
|
|
|
m_cache->update();
|
2018-03-16 01:24:03 +01:00
|
|
|
return pipeline;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkComputePipeline::destroyPipelines() {
|
|
|
|
for (const PipelineStruct& pair : m_pipelines)
|
|
|
|
m_vkd->vkDestroyPipeline(m_vkd->device(), pair.pipeline, nullptr);
|
2017-10-13 03:19:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|