2017-10-10 23:32:13 +02:00
|
|
|
#include "dxvk_device.h"
|
|
|
|
#include "dxvk_instance.h"
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
|
|
|
DxvkDevice::DxvkDevice(
|
2017-12-02 16:47:06 +01:00
|
|
|
const Rc<DxvkAdapter>& adapter,
|
|
|
|
const Rc<vk::DeviceFn>& vkd,
|
|
|
|
const VkPhysicalDeviceFeatures& features)
|
2017-10-15 17:56:06 +02:00
|
|
|
: m_adapter (adapter),
|
|
|
|
m_vkd (vkd),
|
2017-12-02 16:47:06 +01:00
|
|
|
m_features (features),
|
2017-10-15 17:56:06 +02:00
|
|
|
m_memory (new DxvkMemoryAllocator(adapter, vkd)),
|
2017-12-07 09:38:31 +01:00
|
|
|
m_renderPassPool (new DxvkRenderPassPool (vkd)),
|
|
|
|
m_pipelineManager (new DxvkPipelineManager(vkd)) {
|
2017-10-10 23:32:13 +02:00
|
|
|
m_vkd->vkGetDeviceQueue(m_vkd->device(),
|
|
|
|
m_adapter->graphicsQueueFamily(), 0,
|
|
|
|
&m_graphicsQueue);
|
|
|
|
m_vkd->vkGetDeviceQueue(m_vkd->device(),
|
|
|
|
m_adapter->presentQueueFamily(), 0,
|
|
|
|
&m_presentQueue);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DxvkDevice::~DxvkDevice() {
|
2017-10-15 17:56:06 +02:00
|
|
|
m_renderPassPool = nullptr;
|
2017-12-07 09:38:31 +01:00
|
|
|
m_pipelineManager = nullptr;
|
2017-10-15 17:56:06 +02:00
|
|
|
m_memory = nullptr;
|
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
m_vkd->vkDeviceWaitIdle(m_vkd->device());
|
|
|
|
m_vkd->vkDestroyDevice(m_vkd->device(), nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkCommandList> DxvkDevice::createCommandList() {
|
|
|
|
return new DxvkCommandList(m_vkd,
|
|
|
|
m_adapter->graphicsQueueFamily());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkContext> DxvkDevice::createContext() {
|
2017-12-03 00:40:58 +01:00
|
|
|
return new DxvkContext(this);
|
2017-10-10 23:32:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkFramebuffer> DxvkDevice::createFramebuffer(
|
|
|
|
const DxvkRenderTargets& renderTargets) {
|
|
|
|
auto format = renderTargets.renderPassFormat();
|
2017-10-15 17:56:06 +02:00
|
|
|
auto renderPass = m_renderPassPool->getRenderPass(format);
|
2017-10-10 23:32:13 +02:00
|
|
|
return new DxvkFramebuffer(m_vkd, renderPass, renderTargets);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-15 14:36:41 +02:00
|
|
|
Rc<DxvkBuffer> DxvkDevice::createBuffer(
|
|
|
|
const DxvkBufferCreateInfo& createInfo,
|
|
|
|
VkMemoryPropertyFlags memoryType) {
|
|
|
|
return new DxvkBuffer(m_vkd,
|
2017-10-15 17:56:06 +02:00
|
|
|
createInfo, *m_memory, memoryType);
|
2017-10-15 14:36:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-21 19:50:57 +01:00
|
|
|
Rc<DxvkBufferView> DxvkDevice::createBufferView(
|
|
|
|
const Rc<DxvkBuffer>& buffer,
|
|
|
|
const DxvkBufferViewCreateInfo& createInfo) {
|
|
|
|
return new DxvkBufferView(m_vkd, buffer, createInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
Rc<DxvkImage> DxvkDevice::createImage(
|
|
|
|
const DxvkImageCreateInfo& createInfo,
|
|
|
|
VkMemoryPropertyFlags memoryType) {
|
2017-11-27 12:01:35 +01:00
|
|
|
return new DxvkImage(m_vkd,
|
|
|
|
createInfo, *m_memory, memoryType);
|
2017-10-10 23:32:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkImageView> DxvkDevice::createImageView(
|
|
|
|
const Rc<DxvkImage>& image,
|
|
|
|
const DxvkImageViewCreateInfo& createInfo) {
|
|
|
|
return new DxvkImageView(m_vkd, image, createInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-03 20:23:26 +01:00
|
|
|
Rc<DxvkSampler> DxvkDevice::createSampler(
|
|
|
|
const DxvkSamplerCreateInfo& createInfo) {
|
|
|
|
return new DxvkSampler(m_vkd, createInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
Rc<DxvkSemaphore> DxvkDevice::createSemaphore() {
|
|
|
|
return new DxvkSemaphore(m_vkd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-20 15:35:29 +01:00
|
|
|
Rc<DxvkShader> DxvkDevice::createShader(
|
|
|
|
VkShaderStageFlagBits stage,
|
2017-12-07 09:38:31 +01:00
|
|
|
uint32_t slotCount,
|
|
|
|
const DxvkResourceSlot* slotInfos,
|
2017-11-20 15:35:29 +01:00
|
|
|
const SpirvCodeBuffer& code) {
|
2017-12-07 09:38:31 +01:00
|
|
|
return new DxvkShader(m_vkd, stage,
|
|
|
|
slotCount, slotInfos, code);
|
2017-12-03 00:40:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkComputePipeline> DxvkDevice::createComputePipeline(
|
2017-12-07 09:38:31 +01:00
|
|
|
const Rc<DxvkShader>& cs) {
|
|
|
|
return m_pipelineManager->createComputePipeline(cs);
|
2017-12-03 00:40:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkGraphicsPipeline> DxvkDevice::createGraphicsPipeline(
|
2017-12-07 09:38:31 +01:00
|
|
|
const Rc<DxvkShader>& vs,
|
|
|
|
const Rc<DxvkShader>& tcs,
|
|
|
|
const Rc<DxvkShader>& tes,
|
|
|
|
const Rc<DxvkShader>& gs,
|
|
|
|
const Rc<DxvkShader>& fs) {
|
|
|
|
return m_pipelineManager->createGraphicsPipeline(vs, tcs, tes, gs, fs);
|
2017-12-03 00:40:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
Rc<DxvkSwapchain> DxvkDevice::createSwapchain(
|
|
|
|
const Rc<DxvkSurface>& surface,
|
|
|
|
const DxvkSwapchainProperties& properties) {
|
|
|
|
return new DxvkSwapchain(this, surface, properties, m_presentQueue);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkFence> DxvkDevice::submitCommandList(
|
|
|
|
const Rc<DxvkCommandList>& commandList,
|
|
|
|
const Rc<DxvkSemaphore>& waitSync,
|
|
|
|
const Rc<DxvkSemaphore>& wakeSync) {
|
|
|
|
Rc<DxvkFence> fence = new DxvkFence(m_vkd);
|
|
|
|
|
2017-12-01 14:27:53 +01:00
|
|
|
VkSemaphore waitSemaphore = VK_NULL_HANDLE;
|
|
|
|
VkSemaphore wakeSemaphore = VK_NULL_HANDLE;
|
2017-10-10 23:32:13 +02:00
|
|
|
|
|
|
|
if (waitSync != nullptr) {
|
|
|
|
waitSemaphore = waitSync->handle();
|
|
|
|
commandList->trackResource(waitSync);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wakeSync != nullptr) {
|
|
|
|
wakeSemaphore = wakeSync->handle();
|
|
|
|
commandList->trackResource(wakeSync);
|
|
|
|
}
|
|
|
|
|
2017-12-01 14:27:53 +01:00
|
|
|
commandList->submit(m_graphicsQueue,
|
|
|
|
waitSemaphore, wakeSemaphore, fence->handle());
|
2017-10-10 23:32:13 +02:00
|
|
|
|
2017-10-11 09:51:22 +02:00
|
|
|
// TODO Delay synchronization by putting these into a ring buffer
|
2017-10-11 00:27:33 +02:00
|
|
|
fence->wait(std::numeric_limits<uint64_t>::max());
|
|
|
|
commandList->reset();
|
2017-10-10 23:32:13 +02:00
|
|
|
return fence;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkDevice::waitForIdle() const {
|
|
|
|
if (m_vkd->vkDeviceWaitIdle(m_vkd->device()) != VK_SUCCESS)
|
|
|
|
throw DxvkError("DxvkDevice::waitForIdle: Operation failed");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|