#pragma once #include "dxvk_adapter.h" #include "dxvk_buffer.h" #include "dxvk_compute.h" #include "dxvk_constant_state.h" #include "dxvk_context.h" #include "dxvk_extensions.h" #include "dxvk_framebuffer.h" #include "dxvk_image.h" #include "dxvk_memory.h" #include "dxvk_options.h" #include "dxvk_pipecache.h" #include "dxvk_pipemanager.h" #include "dxvk_queue.h" #include "dxvk_recycler.h" #include "dxvk_renderpass.h" #include "dxvk_sampler.h" #include "dxvk_shader.h" #include "dxvk_stats.h" #include "dxvk_swapchain.h" #include "dxvk_sync.h" namespace dxvk { class DxvkInstance; /** * \brief DXVK device * * Device object. This is responsible for resource creation, * memory allocation, command submission and state tracking. * Rendering commands are recorded into command lists using * contexts. Multiple contexts can be created for a device. */ class DxvkDevice : public RcObject { friend class DxvkSubmissionQueue; constexpr static VkDeviceSize DefaultStagingBufferSize = 4 * 1024 * 1024; public: DxvkDevice( const Rc& adapter, const Rc& vkd, const Rc& extensions, const VkPhysicalDeviceFeatures& features); ~DxvkDevice(); /** * \brief Vulkan device functions * \returns Vulkan device functions */ Rc vkd() const { return m_vkd; } /** * \brief Logical device handle * \returns The device handle */ VkDevice handle() const { return m_vkd->device(); } /** * \brief The adapter * * The physical device that the * device has been created for. * \returns Adapter */ Rc adapter() const { return m_adapter; } /** * \brief Checks whether an option is enabled * * \param [in] option The option to check for * \returns \c true if the option is enabled */ bool hasOption(DxvkOption option) const { return m_options.test(option); } /** * \brief Enabled device extensions * \returns Enabled device extensions */ const DxvkDeviceExtensions& extensions() const { return *m_extensions; } /** * \brief Enabled device features * \returns Enabled features */ const VkPhysicalDeviceFeatures& features() const { return m_features; } /** * \brief Allocates a physical buffer * * \param [in] createInfo Buffer create info * \param [in] sliceCount Buffer slice count * \param [in] memoryType Memory property flags * \returns The buffer resource object */ Rc allocPhysicalBuffer( const DxvkBufferCreateInfo& createInfo, VkDeviceSize sliceCount, VkMemoryPropertyFlags memoryType); /** * \brief Allocates a staging buffer * * Returns a staging buffer that is at least as large * as the requested size. It is usually bigger so that * a single staging buffer may serve multiple allocations. * \param [in] size Minimum buffer size * \returns The staging buffer */ Rc allocStagingBuffer( VkDeviceSize size); /** * \brief Recycles a staging buffer * * When a staging buffer is no longer needed, it should * be returned to the device so that it can be reused * for subsequent allocations. * \param [in] buffer The buffer */ void recycleStagingBuffer( const Rc& buffer); /** * \brief Creates a command list * \returns The command list */ Rc createCommandList(); /** * \brief Creates a context * * Creates a context object that can * be used to record command buffers. * \returns The context object */ Rc createContext(); /** * \brief Creates framebuffer for a set of render targets * * Automatically deduces framebuffer dimensions * from the supplied render target views. * \param [in] renderTargets Render targets * \returns The framebuffer object */ Rc createFramebuffer( const DxvkRenderTargets& renderTargets); /** * \brief Creates a buffer object * * \param [in] createInfo Buffer create info * \param [in] memoryType Memory type flags * \returns The buffer object */ Rc createBuffer( const DxvkBufferCreateInfo& createInfo, VkMemoryPropertyFlags memoryType); /** * \brief Creates a buffer view * * \param [in] buffer The buffer to view * \param [in] createInfo Buffer view properties * \returns The buffer view object */ Rc createBufferView( const Rc& buffer, const DxvkBufferViewCreateInfo& createInfo); /** * \brief Creates an image object * * \param [in] createInfo Image create info * \param [in] memoryType Memory type flags * \returns The image object */ Rc createImage( const DxvkImageCreateInfo& createInfo, VkMemoryPropertyFlags memoryType); /** * \brief Creates an image view * * \param [in] image The image to create a view for * \param [in] createInfo Image view create info * \returns The image view */ Rc createImageView( const Rc& image, const DxvkImageViewCreateInfo& createInfo); /** * \brief Creates a sampler object * * \param [in] createInfo Sampler parameters * \returns Newly created sampler object */ Rc createSampler( const DxvkSamplerCreateInfo& createInfo); /** * \brief Creates a semaphore object * \returns Newly created semaphore */ Rc createSemaphore(); /** * \brief Creates a shader module * * \param [in] stage Shader stage * \param [in] slotCount Resource slot count * \param [in] slotInfos Resource slot descriptions * \param [in] iface Inter-stage interface slots * \param [in] code Shader code * \returns New shader module */ Rc createShader( VkShaderStageFlagBits stage, uint32_t slotCount, const DxvkResourceSlot* slotInfos, const DxvkInterfaceSlots& iface, const SpirvCodeBuffer& code); /** * \brief Retrieves a compute pipeline * * \param [in] layout Pipeline binding layout * \param [in] cs Compute shader * \returns The compute pipeline */ Rc createComputePipeline( const Rc& cs); /** * \brief Retrieves a graphics pipeline object * * \param [in] vs Vertex shader * \param [in] tcs Tessellation control shader * \param [in] tes Tessellation evaluation shader * \param [in] gs Geometry shader * \param [in] fs Fragment shader * \returns The graphics pipeline */ Rc createGraphicsPipeline( const Rc& vs, const Rc& tcs, const Rc& tes, const Rc& gs, const Rc& fs); /** * \brief Creates a swap chain * * \param [in] surface The target surface * \param [in] properties Swapchain properties * \returns The swapchain object */ Rc createSwapchain( const Rc& surface, const DxvkSwapchainProperties& properties); /** * \brief Presents a swap chain image * * This is implicitly called by the swap chain class * when presenting an image. Do not use this directly. * \param [in] presentInfo Swap image present info * \returns Present status */ VkResult presentSwapImage( const VkPresentInfoKHR& presentInfo); /** * \brief Submits a command list * * Synchronization arguments are optional. * \param [in] commandList The command list to submit * \param [in] waitSync (Optional) Semaphore to wait on * \param [in] wakeSync (Optional) Semaphore to notify * \returns Synchronization fence */ Rc submitCommandList( const Rc& commandList, const Rc& waitSync, const Rc& wakeSync); /** * \brief Waits until the device becomes idle * * Waits for the GPU to complete the execution of all * previously submitted command buffers. This may be * used to ensure that resources that were previously * used by the GPU can be safely destroyed. */ void waitForIdle(); /** * \brief Retrieves stat counters * \returns Stat counters */ DxvkStatCounters queryCounters() const { return m_statCounters; } private: Rc m_adapter; Rc m_vkd; Rc m_extensions; VkPhysicalDeviceFeatures m_features; Rc m_memory; Rc m_renderPassPool; Rc m_pipelineCache; Rc m_pipelineManager; DxvkOptions m_options; std::mutex m_submissionLock; VkQueue m_graphicsQueue = VK_NULL_HANDLE; VkQueue m_presentQueue = VK_NULL_HANDLE; // TODO fine-tune buffer sizes DxvkRecycler m_recycledCommandLists; DxvkRecycler m_recycledStagingBuffers; DxvkStatCounters m_statCounters; DxvkSubmissionQueue m_submissionQueue; void recycleCommandList( const Rc& cmdList); }; }