2017-10-10 23:32:13 +02:00
|
|
|
#include "dxvk_device.h"
|
|
|
|
#include "dxvk_instance.h"
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
|
|
|
DxvkDevice::DxvkDevice(
|
|
|
|
const Rc<DxvkAdapter>& adapter,
|
|
|
|
const Rc<vk::DeviceFn>& vkd)
|
|
|
|
: m_adapter (adapter),
|
|
|
|
m_vkd (vkd),
|
|
|
|
m_memory (adapter, vkd),
|
|
|
|
m_renderPassPool(vkd) {
|
2017-10-11 00:27:33 +02:00
|
|
|
TRACE(this, adapter);
|
|
|
|
|
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-11 00:27:33 +02:00
|
|
|
TRACE(this);
|
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-10-14 23:52:47 +02:00
|
|
|
return new DxvkContext(this);
|
2017-10-10 23:32:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkFramebuffer> DxvkDevice::createFramebuffer(
|
|
|
|
const DxvkRenderTargets& renderTargets) {
|
|
|
|
auto format = renderTargets.renderPassFormat();
|
|
|
|
auto renderPass = m_renderPassPool.getRenderPass(format);
|
|
|
|
return new DxvkFramebuffer(m_vkd, renderPass, renderTargets);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkImage> DxvkDevice::createImage(
|
|
|
|
const DxvkImageCreateInfo& createInfo,
|
|
|
|
VkMemoryPropertyFlags memoryType) {
|
2017-10-11 09:51:22 +02:00
|
|
|
// TODO implement
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkSemaphore> DxvkDevice::createSemaphore() {
|
|
|
|
return new DxvkSemaphore(m_vkd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-14 23:52:47 +02:00
|
|
|
Rc<DxvkShader> DxvkDevice::createShader(
|
|
|
|
VkShaderStageFlagBits stage,
|
|
|
|
DxvkSpirvCodeBuffer&& code,
|
|
|
|
uint32_t numResourceSlots,
|
|
|
|
const DxvkResourceSlot* resourceSlots) {
|
|
|
|
return new DxvkShader(stage,
|
|
|
|
std::move(code),
|
|
|
|
numResourceSlots,
|
|
|
|
resourceSlots);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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) {
|
2017-10-11 00:27:33 +02:00
|
|
|
TRACE(this, commandList, waitSync, wakeSync);
|
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
Rc<DxvkFence> fence = new DxvkFence(m_vkd);
|
|
|
|
|
|
|
|
VkCommandBuffer commandBuffer = commandList->handle();
|
|
|
|
VkSemaphore waitSemaphore = VK_NULL_HANDLE;
|
|
|
|
VkSemaphore wakeSemaphore = VK_NULL_HANDLE;
|
|
|
|
|
|
|
|
if (waitSync != nullptr) {
|
|
|
|
waitSemaphore = waitSync->handle();
|
|
|
|
commandList->trackResource(waitSync);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wakeSync != nullptr) {
|
|
|
|
wakeSemaphore = wakeSync->handle();
|
|
|
|
commandList->trackResource(wakeSync);
|
|
|
|
}
|
|
|
|
|
|
|
|
const VkPipelineStageFlags waitStageMask
|
|
|
|
= VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
|
|
|
|
|
|
|
VkSubmitInfo info;
|
|
|
|
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
|
|
info.pNext = nullptr;
|
|
|
|
info.waitSemaphoreCount = waitSemaphore == VK_NULL_HANDLE ? 0 : 1;
|
|
|
|
info.pWaitSemaphores = &waitSemaphore;
|
|
|
|
info.pWaitDstStageMask = &waitStageMask;
|
|
|
|
info.commandBufferCount = commandBuffer == VK_NULL_HANDLE ? 0 : 1;
|
|
|
|
info.pCommandBuffers = &commandBuffer;
|
|
|
|
info.signalSemaphoreCount = wakeSemaphore == VK_NULL_HANDLE ? 0 : 1;
|
|
|
|
info.pSignalSemaphores = &wakeSemaphore;
|
|
|
|
|
|
|
|
if (m_vkd->vkQueueSubmit(m_graphicsQueue, 1, &info, fence->handle()) != VK_SUCCESS)
|
|
|
|
throw DxvkError("DxvkDevice::submitCommandList: Command submission failed");
|
|
|
|
|
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 {
|
2017-10-11 00:27:33 +02:00
|
|
|
TRACE(this);
|
2017-10-10 23:32:13 +02:00
|
|
|
if (m_vkd->vkDeviceWaitIdle(m_vkd->device()) != VK_SUCCESS)
|
|
|
|
throw DxvkError("DxvkDevice::waitForIdle: Operation failed");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|