mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 10:54:16 +01:00
[dxvk] Refactored shader binding, client APIs must now create pipelines and pipeline layouts
This commit is contained in:
parent
7ec8e727d2
commit
a6bf7659b0
@ -6,11 +6,11 @@ strip = '/usr/bin/x86_64-w64-mingw32-strip'
|
||||
exe_wrapper = 'wine'
|
||||
|
||||
[properties]
|
||||
cpp_args = ['-std=c++17']
|
||||
cpp_args = ['-std=c++17', '-Og', '-ggdb']
|
||||
cpp_link_args = ['-static', '-static-libgcc', '-static-libstdc++']
|
||||
|
||||
[host_machine]
|
||||
system = 'windows'
|
||||
cpu_family = 'x86_64'
|
||||
cpu = 'x86_64'
|
||||
endian = 'little'
|
||||
endian = 'little'
|
||||
|
@ -35,8 +35,7 @@ namespace dxvk {
|
||||
|
||||
// Set up context state. The shader bindings and the
|
||||
// constant state objects will never be modified.
|
||||
m_context->bindShader(VK_SHADER_STAGE_VERTEX_BIT, createVertexShader());
|
||||
m_context->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, createFragmentShader());
|
||||
m_context->bindGraphicsPipeline(createPipeline());
|
||||
|
||||
m_context->setInputAssemblyState(
|
||||
new DxvkInputAssemblyState(
|
||||
@ -135,6 +134,8 @@ namespace dxvk {
|
||||
m_context->setViewports(1, &viewport, &scissor);
|
||||
|
||||
// TODO bind back buffer as a shader resource
|
||||
// m_context->bindSampler(0, m_sampler);
|
||||
// m_context->bindSampledImage(1, view);
|
||||
m_context->draw(4, 1, 0, 0);
|
||||
|
||||
m_device->submitCommandList(
|
||||
@ -322,4 +323,27 @@ namespace dxvk {
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT, module.compile());
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkBindingLayout> DxgiPresenter::createBindingLayout() {
|
||||
std::array<DxvkBindingInfo, 2> bindings;
|
||||
bindings.at(0).type = VK_DESCRIPTOR_TYPE_SAMPLER;
|
||||
bindings.at(0).stages = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
|
||||
bindings.at(1).type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
bindings.at(1).stages = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
|
||||
return m_device->createBindingLayout(
|
||||
bindings.size(), bindings.data());
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkGraphicsPipeline> DxgiPresenter::createPipeline() {
|
||||
const Rc<DxvkShader> vs = this->createVertexShader();
|
||||
const Rc<DxvkShader> fs = this->createFragmentShader();
|
||||
|
||||
return m_device->createGraphicsPipeline(
|
||||
this->createBindingLayout(),
|
||||
vs, nullptr, nullptr, nullptr, fs);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -55,6 +55,10 @@ namespace dxvk {
|
||||
Rc<DxvkShader> createVertexShader();
|
||||
Rc<DxvkShader> createFragmentShader();
|
||||
|
||||
Rc<DxvkBindingLayout> createBindingLayout();
|
||||
|
||||
Rc<DxvkGraphicsPipeline> createPipeline();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -341,6 +341,7 @@ namespace dxvk {
|
||||
| VK_ACCESS_TRANSFER_READ_BIT
|
||||
| VK_ACCESS_SHADER_READ_BIT;
|
||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageInfo.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
if (dxvkDevice->features().geometryShader)
|
||||
imageInfo.stages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
|
||||
|
@ -91,40 +91,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkCommandList::bindShaderResources(
|
||||
VkPipelineBindPoint pipeline,
|
||||
VkPipelineLayout pipelineLayout,
|
||||
VkDescriptorSetLayout descriptorLayout,
|
||||
uint32_t bindingCount,
|
||||
const DxvkResourceBinding* bindings) {
|
||||
VkDescriptorSet dset = m_descAlloc.alloc(descriptorLayout);
|
||||
|
||||
if (bindingCount > m_descriptorSetWrites.size())
|
||||
m_descriptorSetWrites.resize(bindingCount);
|
||||
|
||||
for (uint32_t i = 0; i < bindingCount; i++) {
|
||||
VkWriteDescriptorSet& info = m_descriptorSetWrites.at(i);
|
||||
|
||||
info.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
info.pNext = nullptr;
|
||||
info.dstSet = dset;
|
||||
info.dstBinding = i;
|
||||
info.dstArrayElement = 0;
|
||||
info.descriptorCount = 1;
|
||||
info.descriptorType = bindings[i].type;
|
||||
info.pImageInfo = &bindings[i].image;
|
||||
info.pBufferInfo = &bindings[i].buffer;
|
||||
info.pTexelBufferView = nullptr;
|
||||
}
|
||||
|
||||
m_vkd->vkUpdateDescriptorSets(m_vkd->device(),
|
||||
bindingCount, m_descriptorSetWrites.data(), 0, nullptr);
|
||||
|
||||
m_vkd->vkCmdBindDescriptorSets(m_buffer,
|
||||
pipeline, pipelineLayout, 0, 1, &dset, 0, nullptr);
|
||||
}
|
||||
|
||||
|
||||
void DxvkCommandList::cmdBeginRenderPass(
|
||||
const VkRenderPassBeginInfo* pRenderPassBegin,
|
||||
VkSubpassContents contents) {
|
||||
|
@ -76,13 +76,6 @@ namespace dxvk {
|
||||
*/
|
||||
void reset();
|
||||
|
||||
void bindShaderResources(
|
||||
VkPipelineBindPoint pipeline,
|
||||
VkPipelineLayout pipelineLayout,
|
||||
VkDescriptorSetLayout descriptorLayout,
|
||||
uint32_t bindingCount,
|
||||
const DxvkResourceBinding* bindings);
|
||||
|
||||
void cmdBeginRenderPass(
|
||||
const VkRenderPassBeginInfo* pRenderPassBegin,
|
||||
VkSubpassContents contents);
|
||||
|
@ -3,72 +3,30 @@
|
||||
namespace dxvk {
|
||||
|
||||
DxvkComputePipeline::DxvkComputePipeline(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkShader>& shader)
|
||||
: m_vkd(vkd), m_shader(shader) {
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkBindingLayout>& layout,
|
||||
const Rc<DxvkShader>& cs)
|
||||
: m_vkd(vkd), m_layout(layout), m_cs(cs) {
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings;
|
||||
|
||||
// TODO re-implement shader slots and bindings
|
||||
// for (uint32_t i = 0; i < shader->slotCount(); i++)
|
||||
// bindings.push_back(shader->slotBinding(0, i));
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo dlayout;
|
||||
dlayout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
dlayout.pNext = nullptr;
|
||||
dlayout.flags = 0;
|
||||
dlayout.bindingCount = bindings.size();
|
||||
dlayout.pBindings = bindings.data();
|
||||
|
||||
if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(),
|
||||
&dlayout, nullptr, &m_descriptorSetLayout) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to create descriptor set layout");
|
||||
|
||||
VkPipelineLayoutCreateInfo playout;
|
||||
playout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
playout.pNext = nullptr;
|
||||
playout.flags = 0;
|
||||
playout.setLayoutCount = 1;
|
||||
playout.pSetLayouts = &m_descriptorSetLayout;
|
||||
playout.pushConstantRangeCount = 0;
|
||||
playout.pPushConstantRanges = nullptr;
|
||||
|
||||
if (m_vkd->vkCreatePipelineLayout(m_vkd->device(),
|
||||
&playout, nullptr, &m_pipelineLayout) != VK_SUCCESS) {
|
||||
this->destroyObjects();
|
||||
throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to create pipeline layout");
|
||||
}
|
||||
|
||||
VkComputePipelineCreateInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
||||
info.pNext = nullptr;
|
||||
info.flags = 0;
|
||||
info.stage = m_shader->stageInfo();
|
||||
info.layout = m_pipelineLayout;
|
||||
info.stage = cs->stageInfo();
|
||||
info.layout = this->pipelineLayout();
|
||||
info.basePipelineHandle = VK_NULL_HANDLE;
|
||||
info.basePipelineIndex = 0;
|
||||
|
||||
if (m_vkd->vkCreateComputePipelines(m_vkd->device(),
|
||||
VK_NULL_HANDLE, 1, &info, nullptr, &m_pipeline) != VK_SUCCESS) {
|
||||
this->destroyObjects();
|
||||
VK_NULL_HANDLE, 1, &info, nullptr, &m_pipeline) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to compile pipeline");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxvkComputePipeline::~DxvkComputePipeline() {
|
||||
this->destroyObjects();
|
||||
}
|
||||
|
||||
|
||||
void DxvkComputePipeline::destroyObjects() {
|
||||
if (m_pipeline != VK_NULL_HANDLE)
|
||||
m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipeline, nullptr);
|
||||
|
||||
if (m_pipelineLayout != VK_NULL_HANDLE)
|
||||
m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_pipelineLayout, nullptr);
|
||||
|
||||
if (m_descriptorSetLayout != VK_NULL_HANDLE)
|
||||
m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_descriptorSetLayout, nullptr);
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxvk_shader.h"
|
||||
#include "dxvk_pipeline.h"
|
||||
#include "dxvk_resource.h"
|
||||
#include "dxvk_shader.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
@ -18,8 +19,9 @@ namespace dxvk {
|
||||
public:
|
||||
|
||||
DxvkComputePipeline(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkShader>& shader);
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkBindingLayout>& layout,
|
||||
const Rc<DxvkShader>& cs);
|
||||
~DxvkComputePipeline();
|
||||
|
||||
/**
|
||||
@ -30,7 +32,7 @@ namespace dxvk {
|
||||
* \returns The descriptor set layout
|
||||
*/
|
||||
VkDescriptorSetLayout descriptorSetLayout() const {
|
||||
return m_descriptorSetLayout;
|
||||
return m_layout->descriptorSetLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,7 +43,7 @@ namespace dxvk {
|
||||
* \returns The descriptor set layout
|
||||
*/
|
||||
VkPipelineLayout pipelineLayout() const {
|
||||
return m_pipelineLayout;
|
||||
return m_layout->pipelineLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,13 +57,10 @@ namespace dxvk {
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
Rc<DxvkShader> m_shader;
|
||||
Rc<DxvkBindingLayout> m_layout;
|
||||
Rc<DxvkShader> m_cs;
|
||||
|
||||
VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE;
|
||||
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
|
||||
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
||||
|
||||
void destroyObjects();
|
||||
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
||||
|
||||
};
|
||||
|
||||
|
@ -4,11 +4,8 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkContext::DxvkContext(
|
||||
const Rc<DxvkDevice>& device,
|
||||
const Rc<DxvkPipelineManager>& pipeMgr)
|
||||
: m_device (device),
|
||||
m_pipeMgr (pipeMgr) {
|
||||
DxvkContext::DxvkContext(const Rc<DxvkDevice>& device)
|
||||
: m_device(device) {
|
||||
|
||||
}
|
||||
|
||||
@ -30,7 +27,6 @@ namespace dxvk {
|
||||
|
||||
m_flags.set(
|
||||
DxvkContextFlag::GpDirtyPipeline,
|
||||
DxvkContextFlag::GpDirtyPipelineState,
|
||||
DxvkContextFlag::GpDirtyDynamicState,
|
||||
DxvkContextFlag::GpDirtyResources,
|
||||
DxvkContextFlag::GpDirtyIndexBuffer,
|
||||
@ -66,27 +62,25 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindShader(
|
||||
VkShaderStageFlagBits stage,
|
||||
const Rc<DxvkShader>& shader) {
|
||||
DxvkShaderStageState* stageState = this->getShaderStage(stage);
|
||||
void DxvkContext::bindComputePipeline(
|
||||
const Rc<DxvkComputePipeline>& pipeline) {
|
||||
m_state.cp = pipeline;
|
||||
|
||||
if (stageState->shader != shader) {
|
||||
stageState->shader = shader;
|
||||
|
||||
if (stage == VK_SHADER_STAGE_COMPUTE_BIT) {
|
||||
m_flags.set(
|
||||
DxvkContextFlag::CpDirtyPipeline,
|
||||
DxvkContextFlag::CpDirtyResources);
|
||||
} else {
|
||||
m_flags.set(
|
||||
DxvkContextFlag::GpDirtyPipeline,
|
||||
DxvkContextFlag::GpDirtyPipelineState,
|
||||
DxvkContextFlag::GpDirtyResources,
|
||||
DxvkContextFlag::GpDirtyVertexBuffers,
|
||||
DxvkContextFlag::GpDirtyIndexBuffer);
|
||||
}
|
||||
}
|
||||
m_flags.set(
|
||||
DxvkContextFlag::CpDirtyPipeline,
|
||||
DxvkContextFlag::CpDirtyResources);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindGraphicsPipeline(
|
||||
const Rc<DxvkGraphicsPipeline>& pipeline) {
|
||||
m_state.gp = pipeline;
|
||||
|
||||
m_flags.set(
|
||||
DxvkContextFlag::GpDirtyPipeline,
|
||||
DxvkContextFlag::GpDirtyResources,
|
||||
DxvkContextFlag::GpDirtyVertexBuffers,
|
||||
DxvkContextFlag::GpDirtyIndexBuffer);
|
||||
}
|
||||
|
||||
|
||||
@ -238,7 +232,7 @@ namespace dxvk {
|
||||
const VkRect2D* scissorRects) {
|
||||
if (m_state.vp.viewportCount != viewportCount) {
|
||||
m_state.vp.viewportCount = viewportCount;
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipeline);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < viewportCount; i++) {
|
||||
@ -254,7 +248,7 @@ namespace dxvk {
|
||||
const Rc<DxvkInputAssemblyState>& state) {
|
||||
if (m_state.co.inputAssemblyState != state) {
|
||||
m_state.co.inputAssemblyState = state;
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipeline);
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,7 +257,7 @@ namespace dxvk {
|
||||
const Rc<DxvkInputLayout>& state) {
|
||||
if (m_state.co.inputLayout != state) {
|
||||
m_state.co.inputLayout = state;
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipeline);
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,7 +266,7 @@ namespace dxvk {
|
||||
const Rc<DxvkRasterizerState>& state) {
|
||||
if (m_state.co.rasterizerState != state) {
|
||||
m_state.co.rasterizerState = state;
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipeline);
|
||||
}
|
||||
}
|
||||
|
||||
@ -281,7 +275,7 @@ namespace dxvk {
|
||||
const Rc<DxvkMultisampleState>& state) {
|
||||
if (m_state.co.multisampleState != state) {
|
||||
m_state.co.multisampleState = state;
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipeline);
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,7 +284,7 @@ namespace dxvk {
|
||||
const Rc<DxvkDepthStencilState>& state) {
|
||||
if (m_state.co.depthStencilState != state) {
|
||||
m_state.co.depthStencilState = state;
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipeline);
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,7 +293,7 @@ namespace dxvk {
|
||||
const Rc<DxvkBlendState>& state) {
|
||||
if (m_state.co.blendState != state) {
|
||||
m_state.co.blendState = state;
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
|
||||
m_flags.set(DxvkContextFlag::GpDirtyPipeline);
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,15 +344,6 @@ namespace dxvk {
|
||||
if (m_flags.test(DxvkContextFlag::GpDirtyPipeline)) {
|
||||
m_flags.clr(DxvkContextFlag::GpDirtyPipeline);
|
||||
|
||||
m_state.activeGraphicsPipeline = m_pipeMgr->getGraphicsPipeline(
|
||||
m_state.vs.shader, m_state.tcs.shader, m_state.tes.shader,
|
||||
m_state.gs.shader, m_state.fs.shader);
|
||||
}
|
||||
|
||||
if (m_flags.test(DxvkContextFlag::GpDirtyPipelineState)
|
||||
&& m_state.activeGraphicsPipeline != nullptr) {
|
||||
m_flags.clr(DxvkContextFlag::GpDirtyPipelineState);
|
||||
|
||||
DxvkGraphicsPipelineStateInfo gpState;
|
||||
gpState.inputAssemblyState = m_state.co.inputAssemblyState;
|
||||
gpState.inputLayout = m_state.co.inputLayout;
|
||||
@ -370,8 +355,8 @@ namespace dxvk {
|
||||
gpState.viewportCount = m_state.vp.viewportCount;
|
||||
|
||||
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
m_state.activeGraphicsPipeline->getPipelineHandle(gpState));
|
||||
m_cmd->trackResource(m_state.activeGraphicsPipeline);
|
||||
m_state.gp->getPipelineHandle(gpState));
|
||||
m_cmd->trackResource(m_state.gp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -440,21 +425,4 @@ namespace dxvk {
|
||||
this->updateVertexBufferBindings();
|
||||
}
|
||||
|
||||
|
||||
DxvkShaderStageState* DxvkContext::getShaderStage(VkShaderStageFlagBits stage) {
|
||||
switch (stage) {
|
||||
case VK_SHADER_STAGE_VERTEX_BIT: return &m_state.vs;
|
||||
case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return &m_state.tcs;
|
||||
case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return &m_state.tes;
|
||||
case VK_SHADER_STAGE_GEOMETRY_BIT: return &m_state.gs;
|
||||
case VK_SHADER_STAGE_FRAGMENT_BIT: return &m_state.fs;
|
||||
case VK_SHADER_STAGE_COMPUTE_BIT: return &m_state.cs;
|
||||
|
||||
default:
|
||||
throw DxvkError(str::format(
|
||||
"DxvkContext::getShaderStage: Invalid stage bit: ",
|
||||
static_cast<uint32_t>(stage)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
#include "dxvk_cmdlist.h"
|
||||
#include "dxvk_context_state.h"
|
||||
#include "dxvk_data.h"
|
||||
#include "dxvk_pipemgr.h"
|
||||
#include "dxvk_util.h"
|
||||
|
||||
namespace dxvk {
|
||||
@ -20,9 +19,7 @@ namespace dxvk {
|
||||
|
||||
public:
|
||||
|
||||
DxvkContext(
|
||||
const Rc<DxvkDevice>& device,
|
||||
const Rc<DxvkPipelineManager>& pipeMgr);
|
||||
DxvkContext(const Rc<DxvkDevice>& device);
|
||||
~DxvkContext();
|
||||
|
||||
/**
|
||||
@ -64,18 +61,26 @@ namespace dxvk {
|
||||
const DxvkBufferBinding& buffer);
|
||||
|
||||
/**
|
||||
* \brief Sets shader for a given shader stage
|
||||
* \brief Binds compute pipeline
|
||||
*
|
||||
* Binds a shader to a given stage, while unbinding the
|
||||
* existing one. If \c nullptr is passed as the shader
|
||||
* to bind, the given shader stage will be disabled.
|
||||
* When drawing, at least a vertex shader must be bound.
|
||||
* \param [in] stage The shader stage
|
||||
* \param [in] shader The shader to set
|
||||
* Note that binding a new pipeline implicitly
|
||||
* invalidates all resource bindings that are
|
||||
* used by the pipeline.
|
||||
* \param [in] pipeline The pipeline to bind
|
||||
*/
|
||||
void bindShader(
|
||||
VkShaderStageFlagBits stage,
|
||||
const Rc<DxvkShader>& shader);
|
||||
void bindComputePipeline(
|
||||
const Rc<DxvkComputePipeline>& pipeline);
|
||||
|
||||
/**
|
||||
* \brief Binds graphics pipeline
|
||||
*
|
||||
* Note that binding a new pipeline implicitly
|
||||
* invalidates all bindings that are used by
|
||||
* the pipeline.
|
||||
* \param [in] pipeline The pipeline to bind
|
||||
*/
|
||||
void bindGraphicsPipeline(
|
||||
const Rc<DxvkGraphicsPipeline>& pipeline);
|
||||
|
||||
/**
|
||||
* \brief Binds vertex buffer
|
||||
@ -250,14 +255,15 @@ namespace dxvk {
|
||||
|
||||
private:
|
||||
|
||||
const Rc<DxvkDevice> m_device;
|
||||
const Rc<DxvkPipelineManager> m_pipeMgr;
|
||||
const Rc<DxvkDevice> m_device;
|
||||
|
||||
Rc<DxvkCommandList> m_cmd;
|
||||
DxvkContextFlags m_flags;
|
||||
DxvkContextState m_state;
|
||||
DxvkBarrierSet m_barriers;
|
||||
|
||||
std::vector<VkWriteDescriptorSet> m_descriptorSetWrites;
|
||||
|
||||
void renderPassBegin();
|
||||
void renderPassEnd();
|
||||
|
||||
@ -272,10 +278,6 @@ namespace dxvk {
|
||||
|
||||
void commitComputeState();
|
||||
void commitGraphicsState();
|
||||
|
||||
DxvkShaderStageState* getShaderStage(
|
||||
VkShaderStageFlagBits stage);
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -20,8 +20,7 @@ namespace dxvk {
|
||||
*/
|
||||
enum class DxvkContextFlag : uint64_t {
|
||||
GpRenderPassBound, ///< Render pass is currently bound
|
||||
GpDirtyPipeline, ///< Graphics pipeline binding are out of date
|
||||
GpDirtyPipelineState, ///< Graphics pipeline state (blending etc.) is dirty
|
||||
GpDirtyPipeline, ///< Graphics pipeline binding or state is out of date
|
||||
GpDirtyDynamicState, ///< Dynamic state needs to be reapplied
|
||||
GpDirtyResources, ///< Graphics pipeline resource bindings are out of date
|
||||
GpDirtyVertexBuffers, ///< Vertex buffer bindings are out of date
|
||||
@ -34,11 +33,6 @@ namespace dxvk {
|
||||
using DxvkContextFlags = Flags<DxvkContextFlag>;
|
||||
|
||||
|
||||
struct DxvkShaderStageState {
|
||||
Rc<DxvkShader> shader;
|
||||
};
|
||||
|
||||
|
||||
struct DxvkVertexInputState {
|
||||
DxvkBufferBinding indexBuffer;
|
||||
std::array<DxvkBufferBinding,
|
||||
@ -65,20 +59,13 @@ namespace dxvk {
|
||||
* and constant pipeline state objects.
|
||||
*/
|
||||
struct DxvkContextState {
|
||||
DxvkShaderStageState vs;
|
||||
DxvkShaderStageState tcs;
|
||||
DxvkShaderStageState tes;
|
||||
DxvkShaderStageState gs;
|
||||
DxvkShaderStageState fs;
|
||||
DxvkShaderStageState cs;
|
||||
|
||||
DxvkVertexInputState vi;
|
||||
DxvkViewportState vp;
|
||||
DxvkOutputMergerState om;
|
||||
DxvkConstantStateObjects co;
|
||||
|
||||
Rc<DxvkGraphicsPipeline> activeGraphicsPipeline;
|
||||
Rc<DxvkComputePipeline> activeComputePipeline;
|
||||
Rc<DxvkGraphicsPipeline> gp;
|
||||
Rc<DxvkComputePipeline> cp;
|
||||
};
|
||||
|
||||
}
|
@ -4,12 +4,6 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
struct DxvkResourceBinding {
|
||||
VkDescriptorType type;
|
||||
VkDescriptorImageInfo image;
|
||||
VkDescriptorBufferInfo buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Descriptor set allocator
|
||||
*
|
||||
|
@ -11,8 +11,7 @@ namespace dxvk {
|
||||
m_vkd (vkd),
|
||||
m_features (features),
|
||||
m_memory (new DxvkMemoryAllocator(adapter, vkd)),
|
||||
m_renderPassPool (new DxvkRenderPassPool (vkd)),
|
||||
m_pipelineManager (new DxvkPipelineManager(vkd)) {
|
||||
m_renderPassPool (new DxvkRenderPassPool (vkd)) {
|
||||
m_vkd->vkGetDeviceQueue(m_vkd->device(),
|
||||
m_adapter->graphicsQueueFamily(), 0,
|
||||
&m_graphicsQueue);
|
||||
@ -23,7 +22,6 @@ namespace dxvk {
|
||||
|
||||
|
||||
DxvkDevice::~DxvkDevice() {
|
||||
m_pipelineManager = nullptr;
|
||||
m_renderPassPool = nullptr;
|
||||
m_memory = nullptr;
|
||||
|
||||
@ -39,7 +37,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
Rc<DxvkContext> DxvkDevice::createContext() {
|
||||
return new DxvkContext(this, m_pipelineManager);
|
||||
return new DxvkContext(this);
|
||||
}
|
||||
|
||||
|
||||
@ -93,6 +91,32 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkBindingLayout> DxvkDevice::createBindingLayout(
|
||||
uint32_t bindingCount,
|
||||
const DxvkBindingInfo* bindingInfos) {
|
||||
return new DxvkBindingLayout(m_vkd, bindingCount, bindingInfos);
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkComputePipeline> DxvkDevice::createComputePipeline(
|
||||
const Rc<DxvkBindingLayout>& layout,
|
||||
const Rc<DxvkShader>& cs) {
|
||||
return new DxvkComputePipeline(m_vkd, layout, cs);
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkGraphicsPipeline> DxvkDevice::createGraphicsPipeline(
|
||||
const Rc<DxvkBindingLayout>& layout,
|
||||
const Rc<DxvkShader>& vs,
|
||||
const Rc<DxvkShader>& tcs,
|
||||
const Rc<DxvkShader>& tes,
|
||||
const Rc<DxvkShader>& gs,
|
||||
const Rc<DxvkShader>& fs) {
|
||||
return new DxvkGraphicsPipeline(m_vkd,
|
||||
layout, vs, tcs, tes, gs, fs);
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkSwapchain> DxvkDevice::createSwapchain(
|
||||
const Rc<DxvkSurface>& surface,
|
||||
const DxvkSwapchainProperties& properties) {
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "dxvk_framebuffer.h"
|
||||
#include "dxvk_image.h"
|
||||
#include "dxvk_memory.h"
|
||||
#include "dxvk_pipemgr.h"
|
||||
#include "dxvk_renderpass.h"
|
||||
#include "dxvk_shader.h"
|
||||
#include "dxvk_swapchain.h"
|
||||
@ -159,6 +158,47 @@ namespace dxvk {
|
||||
VkShaderStageFlagBits stage,
|
||||
const SpirvCodeBuffer& code);
|
||||
|
||||
/**
|
||||
* \brief Creates binding layout
|
||||
*
|
||||
* \param [in] bindingCount Number of bindings
|
||||
* \param [in] bindingInfos Binding descriptions
|
||||
* \returns New binding layout
|
||||
*/
|
||||
Rc<DxvkBindingLayout> createBindingLayout(
|
||||
uint32_t bindingCount,
|
||||
const DxvkBindingInfo* bindingInfos);
|
||||
|
||||
/**
|
||||
* \brief Creates a compute pipeline
|
||||
*
|
||||
* \param [in] layout Pipeline binding layout
|
||||
* \param [in] cs Compute shader
|
||||
* \returns New compute pipeline
|
||||
*/
|
||||
Rc<DxvkComputePipeline> createComputePipeline(
|
||||
const Rc<DxvkBindingLayout>& layout,
|
||||
const Rc<DxvkShader>& cs);
|
||||
|
||||
/**
|
||||
* \brief Creates a graphics pipeline
|
||||
*
|
||||
* \param [in] layout Pipeline binding layout
|
||||
* \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 New graphics pipeline
|
||||
*/
|
||||
Rc<DxvkGraphicsPipeline> createGraphicsPipeline(
|
||||
const Rc<DxvkBindingLayout>& layout,
|
||||
const Rc<DxvkShader>& vs,
|
||||
const Rc<DxvkShader>& tcs,
|
||||
const Rc<DxvkShader>& tes,
|
||||
const Rc<DxvkShader>& gs,
|
||||
const Rc<DxvkShader>& fs);
|
||||
|
||||
/**
|
||||
* \brief Creates a swap chain
|
||||
*
|
||||
@ -202,7 +242,6 @@ namespace dxvk {
|
||||
|
||||
Rc<DxvkMemoryAllocator> m_memory;
|
||||
Rc<DxvkRenderPassPool> m_renderPassPool;
|
||||
Rc<DxvkPipelineManager> m_pipelineManager;
|
||||
|
||||
VkQueue m_graphicsQueue;
|
||||
VkQueue m_presentQueue;
|
||||
|
@ -39,47 +39,21 @@ namespace dxvk {
|
||||
|
||||
|
||||
DxvkGraphicsPipeline::DxvkGraphicsPipeline(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkShader>& vs,
|
||||
const Rc<DxvkShader>& tcs,
|
||||
const Rc<DxvkShader>& tes,
|
||||
const Rc<DxvkShader>& gs,
|
||||
const Rc<DxvkShader>& fs)
|
||||
: m_vkd(vkd), m_vs(vs), m_tcs(tcs),
|
||||
m_tes(tes), m_gs(gs), m_fs(fs) {
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings;
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkBindingLayout>& layout,
|
||||
const Rc<DxvkShader>& vs,
|
||||
const Rc<DxvkShader>& tcs,
|
||||
const Rc<DxvkShader>& tes,
|
||||
const Rc<DxvkShader>& gs,
|
||||
const Rc<DxvkShader>& fs)
|
||||
: m_vkd(vkd), m_layout(layout),
|
||||
m_vs(vs), m_tcs(tcs), m_tes(tes), m_gs(gs), m_fs(fs) {
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo dlayout;
|
||||
dlayout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
dlayout.pNext = nullptr;
|
||||
dlayout.flags = 0;
|
||||
dlayout.bindingCount = bindings.size();
|
||||
dlayout.pBindings = bindings.data();
|
||||
|
||||
if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(),
|
||||
&dlayout, nullptr, &m_descriptorSetLayout) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to create descriptor set layout");
|
||||
|
||||
VkPipelineLayoutCreateInfo playout;
|
||||
playout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
playout.pNext = nullptr;
|
||||
playout.flags = 0;
|
||||
playout.setLayoutCount = 1;
|
||||
playout.pSetLayouts = &m_descriptorSetLayout;
|
||||
playout.pushConstantRangeCount = 0;
|
||||
playout.pPushConstantRanges = nullptr;
|
||||
|
||||
if (m_vkd->vkCreatePipelineLayout(m_vkd->device(),
|
||||
&playout, nullptr, &m_pipelineLayout) != VK_SUCCESS) {
|
||||
this->destroyObjects();
|
||||
throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to create pipeline layout");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxvkGraphicsPipeline::~DxvkGraphicsPipeline() {
|
||||
this->destroyPipelines();
|
||||
this->destroyObjects();
|
||||
}
|
||||
|
||||
|
||||
@ -145,7 +119,7 @@ namespace dxvk {
|
||||
info.pDepthStencilState = &state.depthStencilState->info();
|
||||
info.pColorBlendState = &state.blendState->info();
|
||||
info.pDynamicState = &dsInfo;
|
||||
info.layout = m_pipelineLayout;
|
||||
info.layout = this->pipelineLayout();
|
||||
info.renderPass = state.renderPass;
|
||||
info.subpass = 0;
|
||||
info.basePipelineHandle = VK_NULL_HANDLE;
|
||||
@ -159,15 +133,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkGraphicsPipeline::destroyObjects() {
|
||||
if (m_pipelineLayout != VK_NULL_HANDLE)
|
||||
m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_pipelineLayout, nullptr);
|
||||
|
||||
if (m_descriptorSetLayout != VK_NULL_HANDLE)
|
||||
m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_descriptorSetLayout, nullptr);
|
||||
}
|
||||
|
||||
|
||||
void DxvkGraphicsPipeline::destroyPipelines() {
|
||||
for (const auto& pair : m_pipelines) {
|
||||
m_vkd->vkDestroyPipeline(
|
||||
|
@ -5,8 +5,9 @@
|
||||
|
||||
#include "dxvk_constant_state.h"
|
||||
#include "dxvk_hash.h"
|
||||
#include "dxvk_shader.h"
|
||||
#include "dxvk_pipeline.h"
|
||||
#include "dxvk_resource.h"
|
||||
#include "dxvk_shader.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
@ -48,12 +49,13 @@ namespace dxvk {
|
||||
public:
|
||||
|
||||
DxvkGraphicsPipeline(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkShader>& vs,
|
||||
const Rc<DxvkShader>& tcs,
|
||||
const Rc<DxvkShader>& tes,
|
||||
const Rc<DxvkShader>& gs,
|
||||
const Rc<DxvkShader>& fs);
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkBindingLayout>& layout,
|
||||
const Rc<DxvkShader>& vs,
|
||||
const Rc<DxvkShader>& tcs,
|
||||
const Rc<DxvkShader>& tes,
|
||||
const Rc<DxvkShader>& gs,
|
||||
const Rc<DxvkShader>& fs);
|
||||
~DxvkGraphicsPipeline();
|
||||
|
||||
/**
|
||||
@ -64,18 +66,18 @@ namespace dxvk {
|
||||
* \returns The descriptor set layout
|
||||
*/
|
||||
VkDescriptorSetLayout descriptorSetLayout() const {
|
||||
return m_descriptorSetLayout;
|
||||
return m_layout->descriptorSetLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Pipeline layout layout
|
||||
* \brief Pipeline layout
|
||||
*
|
||||
* The pipeline layout for this pipeline.
|
||||
* Use this to bind descriptor sets.
|
||||
* \returns The descriptor set layout
|
||||
*/
|
||||
VkPipelineLayout pipelineLayout() const {
|
||||
return m_pipelineLayout;
|
||||
return m_layout->pipelineLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,14 +90,13 @@ namespace dxvk {
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
Rc<DxvkShader> m_vs;
|
||||
Rc<DxvkShader> m_tcs;
|
||||
Rc<DxvkShader> m_tes;
|
||||
Rc<DxvkShader> m_gs;
|
||||
Rc<DxvkShader> m_fs;
|
||||
Rc<DxvkBindingLayout> m_layout;
|
||||
|
||||
VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE;
|
||||
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
|
||||
Rc<DxvkShader> m_vs;
|
||||
Rc<DxvkShader> m_tcs;
|
||||
Rc<DxvkShader> m_tes;
|
||||
Rc<DxvkShader> m_gs;
|
||||
Rc<DxvkShader> m_fs;
|
||||
|
||||
std::mutex m_mutex;
|
||||
|
||||
@ -106,7 +107,6 @@ namespace dxvk {
|
||||
VkPipeline compilePipeline(
|
||||
const DxvkGraphicsPipelineStateInfo& state) const;
|
||||
|
||||
void destroyObjects();
|
||||
void destroyPipelines();
|
||||
|
||||
};
|
||||
|
@ -42,6 +42,9 @@ namespace dxvk {
|
||||
|
||||
/// Image tiling mode
|
||||
VkImageTiling tiling;
|
||||
|
||||
/// Common image layout
|
||||
VkImageLayout layout;
|
||||
};
|
||||
|
||||
|
||||
|
72
src/dxvk/dxvk_pipeline.cpp
Normal file
72
src/dxvk/dxvk_pipeline.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
#include "dxvk_pipeline.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkBindingLayout::DxvkBindingLayout(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
uint32_t bindingCount,
|
||||
const DxvkBindingInfo* bindingInfos)
|
||||
: m_vkd(vkd) {
|
||||
|
||||
for (uint32_t i = 0; i < bindingCount; i++) {
|
||||
VkDescriptorSetLayoutBinding binding;
|
||||
binding.binding = i;
|
||||
binding.descriptorType = bindingInfos[i].type;
|
||||
binding.descriptorCount = bindingInfos[i].stages == 0 ? 0 : 1;
|
||||
binding.stageFlags = bindingInfos[i].stages;
|
||||
binding.pImmutableSamplers = nullptr;
|
||||
m_bindings.push_back(binding);
|
||||
}
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo dsetInfo;
|
||||
dsetInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
dsetInfo.pNext = nullptr;
|
||||
dsetInfo.flags = 0;
|
||||
dsetInfo.bindingCount = m_bindings.size();
|
||||
dsetInfo.pBindings = m_bindings.data();
|
||||
|
||||
if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(),
|
||||
&dsetInfo, nullptr, &m_descriptorSetLayout) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkBindingLayout: Failed to create descriptor set layout");
|
||||
|
||||
VkPipelineLayoutCreateInfo pipeInfo;
|
||||
pipeInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
pipeInfo.pNext = nullptr;
|
||||
pipeInfo.flags = 0;
|
||||
pipeInfo.setLayoutCount = 1;
|
||||
pipeInfo.pSetLayouts = &m_descriptorSetLayout;
|
||||
pipeInfo.pushConstantRangeCount = 0;
|
||||
pipeInfo.pPushConstantRanges = nullptr;
|
||||
|
||||
if (m_vkd->vkCreatePipelineLayout(m_vkd->device(),
|
||||
&pipeInfo, nullptr, &m_pipelineLayout) != VK_SUCCESS) {
|
||||
m_vkd->vkDestroyDescriptorSetLayout(
|
||||
m_vkd->device(), m_descriptorSetLayout, nullptr);
|
||||
throw DxvkError("DxvkBindingLayout: Failed to create pipeline layout");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxvkBindingLayout::~DxvkBindingLayout() {
|
||||
if (m_pipelineLayout != VK_NULL_HANDLE) {
|
||||
m_vkd->vkDestroyPipelineLayout(
|
||||
m_vkd->device(), m_pipelineLayout, nullptr);
|
||||
}
|
||||
|
||||
if (m_descriptorSetLayout != VK_NULL_HANDLE) {
|
||||
m_vkd->vkDestroyDescriptorSetLayout(
|
||||
m_vkd->device(), m_descriptorSetLayout, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxvkBindingInfo DxvkBindingLayout::binding(uint32_t id) const {
|
||||
const VkDescriptorSetLayoutBinding& bindingInfo = m_bindings.at(id);
|
||||
|
||||
DxvkBindingInfo result;
|
||||
result.type = bindingInfo.descriptorType;
|
||||
result.stages = bindingInfo.stageFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
80
src/dxvk/dxvk_pipeline.h
Normal file
80
src/dxvk/dxvk_pipeline.h
Normal file
@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxvk_include.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Shader interface binding
|
||||
*
|
||||
* Corresponds to a single descriptor binding in
|
||||
* Vulkan. DXVK does not use descriptor arrays.
|
||||
* Instead, each binding stores one descriptor.
|
||||
*/
|
||||
struct DxvkBindingInfo {
|
||||
VkDescriptorType type;
|
||||
VkShaderStageFlags stages;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Shader interface
|
||||
*
|
||||
* Describes shader resource bindings
|
||||
* for a graphics or compute pipeline.
|
||||
*/
|
||||
class DxvkBindingLayout : public RcObject {
|
||||
|
||||
public:
|
||||
|
||||
DxvkBindingLayout(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
uint32_t bindingCount,
|
||||
const DxvkBindingInfo* bindingInfos);
|
||||
|
||||
~DxvkBindingLayout();
|
||||
|
||||
/**
|
||||
* \brief Number of resource bindings
|
||||
* \returns Resource binding count
|
||||
*/
|
||||
uint32_t numBindings() const {
|
||||
return m_bindings.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves binding info
|
||||
*
|
||||
* \param [in] binding ID
|
||||
* \returns Binding info
|
||||
*/
|
||||
DxvkBindingInfo binding(uint32_t id) const;
|
||||
|
||||
/**
|
||||
* \brief Descriptor set layout handle
|
||||
* \returns Descriptor set layout handle
|
||||
*/
|
||||
VkDescriptorSetLayout descriptorSetLayout() const {
|
||||
return m_descriptorSetLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Pipeline layout handle
|
||||
* \returns Pipeline layout handle
|
||||
*/
|
||||
VkPipelineLayout pipelineLayout() const {
|
||||
return m_pipelineLayout;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
|
||||
VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE;
|
||||
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
|
||||
|
||||
std::vector<VkDescriptorSetLayoutBinding> m_bindings;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
#include "dxvk_pipemgr.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkPipelineManager::DxvkPipelineManager(
|
||||
const Rc<vk::DeviceFn>& vkd)
|
||||
: m_vkd(vkd) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
DxvkPipelineManager::~DxvkPipelineManager() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkComputePipeline> DxvkPipelineManager::getComputePipeline(const Rc<DxvkShader>& cs) {
|
||||
if (cs == nullptr)
|
||||
return nullptr;
|
||||
|
||||
DxvkPipelineKey<1> key;
|
||||
key.setShader(0, cs);
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
auto pair = m_computePipelines.find(key);
|
||||
if (pair != m_computePipelines.end())
|
||||
return pair->second;
|
||||
|
||||
Rc<DxvkComputePipeline> pipeline = new DxvkComputePipeline(m_vkd, cs);
|
||||
m_computePipelines.insert(std::make_pair(key, pipeline));
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkGraphicsPipeline> DxvkPipelineManager::getGraphicsPipeline(
|
||||
const Rc<DxvkShader>& vs,
|
||||
const Rc<DxvkShader>& tcs,
|
||||
const Rc<DxvkShader>& tes,
|
||||
const Rc<DxvkShader>& gs,
|
||||
const Rc<DxvkShader>& fs) {
|
||||
if (vs == nullptr)
|
||||
return nullptr;
|
||||
|
||||
DxvkPipelineKey<5> key;
|
||||
key.setShader(0, vs);
|
||||
key.setShader(1, tcs);
|
||||
key.setShader(2, tes);
|
||||
key.setShader(3, gs);
|
||||
key.setShader(4, fs);
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
auto pair = m_graphicsPipelines.find(key);
|
||||
if (pair != m_graphicsPipelines.end())
|
||||
return pair->second;
|
||||
|
||||
Rc<DxvkGraphicsPipeline> pipeline = new DxvkGraphicsPipeline(m_vkd, vs, tcs, tes, gs, fs);
|
||||
m_graphicsPipelines.insert(std::make_pair(key, pipeline));
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "dxvk_compute.h"
|
||||
#include "dxvk_hash.h"
|
||||
#include "dxvk_graphics.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Pipeline key
|
||||
*
|
||||
* Stores a fixed-size set of shaders in order
|
||||
* to identify a shader pipeline object.
|
||||
*/
|
||||
template<size_t N>
|
||||
class DxvkPipelineKey {
|
||||
|
||||
public:
|
||||
|
||||
void setShader(
|
||||
size_t id,
|
||||
const Rc<DxvkShader>& shader) {
|
||||
m_shaders.at(id) = shader;
|
||||
}
|
||||
|
||||
size_t hash() const {
|
||||
std::hash<DxvkShader*> phash;
|
||||
|
||||
DxvkHashState state;
|
||||
for (size_t i = 0; i < N; i++)
|
||||
state.add(phash(m_shaders[i].ptr()));
|
||||
return state;
|
||||
}
|
||||
|
||||
bool operator == (const DxvkPipelineKey& other) const {
|
||||
bool result = true;
|
||||
for (size_t i = 0; (i < N) && result; i++)
|
||||
result &= m_shaders[i] == other.m_shaders[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator != (const DxvkPipelineKey& other) const {
|
||||
return !this->operator == (other);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::array<Rc<DxvkShader>, N> m_shaders;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Pipeline manager
|
||||
*
|
||||
* Creates and manages pipeline objects
|
||||
* for various combinations of shaders.
|
||||
*/
|
||||
class DxvkPipelineManager : public RcObject {
|
||||
|
||||
public:
|
||||
|
||||
DxvkPipelineManager(
|
||||
const Rc<vk::DeviceFn>& vkd);
|
||||
~DxvkPipelineManager();
|
||||
|
||||
/**
|
||||
* \brief Retrieves compute pipeline
|
||||
*
|
||||
* Retrieves a compute pipeline object for the given
|
||||
* shader. If no such pipeline object exists, a new
|
||||
* one will be created.
|
||||
* \param [in] cs Compute shader
|
||||
* \returns Compute pipeline
|
||||
*/
|
||||
Rc<DxvkComputePipeline> getComputePipeline(
|
||||
const Rc<DxvkShader>& cs);
|
||||
|
||||
/**
|
||||
* \brief Retrieves graphics pipeline
|
||||
*
|
||||
* Retrieves a graphics pipeline object for the given
|
||||
* combination of shaders. If no such pipeline object
|
||||
* exists, a new one will be created.
|
||||
* \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 Graphics pipeline
|
||||
*/
|
||||
Rc<DxvkGraphicsPipeline> getGraphicsPipeline(
|
||||
const Rc<DxvkShader>& vs,
|
||||
const Rc<DxvkShader>& tcs,
|
||||
const Rc<DxvkShader>& tes,
|
||||
const Rc<DxvkShader>& gs,
|
||||
const Rc<DxvkShader>& fs);
|
||||
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
|
||||
std::mutex m_mutex;
|
||||
|
||||
std::unordered_map<
|
||||
DxvkPipelineKey<1>,
|
||||
Rc<DxvkComputePipeline>,
|
||||
DxvkHash> m_computePipelines;
|
||||
|
||||
std::unordered_map<
|
||||
DxvkPipelineKey<5>,
|
||||
Rc<DxvkGraphicsPipeline>,
|
||||
DxvkHash> m_graphicsPipelines;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -9,19 +9,14 @@
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Shader resource type
|
||||
* \brief Resource slot
|
||||
*
|
||||
* Enumerates the types of resources
|
||||
* that can be accessed by shaders.
|
||||
* Describes the type of a single resource
|
||||
* binding that a shader can access.
|
||||
*/
|
||||
enum class DxvkResourceType : uint32_t {
|
||||
ImageSampler = VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||
SampledImage = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
StorageImage = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||
UniformBuffer = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
StorageBuffer = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
UniformTexelBuffer = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
|
||||
StorageTexelBuffer = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
|
||||
struct DxvkResourceSlot {
|
||||
uint32_t binding;
|
||||
VkDescriptorType type;
|
||||
};
|
||||
|
||||
|
||||
|
@ -137,28 +137,33 @@ namespace dxvk {
|
||||
auto swapImages = this->retrieveSwapImages();
|
||||
m_framebuffers.resize(swapImages.size());
|
||||
|
||||
DxvkImageCreateInfo imageInfo;
|
||||
imageInfo.type = VK_IMAGE_TYPE_2D;
|
||||
imageInfo.format = fmt.format;
|
||||
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageInfo.extent.width = swapInfo.imageExtent.width;
|
||||
imageInfo.extent.height = swapInfo.imageExtent.height;
|
||||
imageInfo.extent.depth = 1;
|
||||
imageInfo.numLayers = swapInfo.imageArrayLayers;
|
||||
imageInfo.mipLevels = 1;
|
||||
imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageInfo.stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
imageInfo.access = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
|
||||
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
|
||||
| VK_ACCESS_MEMORY_READ_BIT;
|
||||
imageInfo.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
DxvkImageViewCreateInfo viewInfo;
|
||||
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewInfo.format = fmt.format;
|
||||
viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewInfo.minLevel = 0;
|
||||
viewInfo.numLevels = 1;
|
||||
viewInfo.minLayer = 0;
|
||||
viewInfo.numLayers = swapInfo.imageArrayLayers;
|
||||
|
||||
for (size_t i = 0; i < swapImages.size(); i++) {
|
||||
DxvkImageCreateInfo imageInfo;
|
||||
imageInfo.type = VK_IMAGE_TYPE_2D;
|
||||
imageInfo.format = fmt.format;
|
||||
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageInfo.extent.width = swapInfo.imageExtent.width;
|
||||
imageInfo.extent.height = swapInfo.imageExtent.height;
|
||||
imageInfo.extent.depth = 1;
|
||||
imageInfo.numLayers = swapInfo.imageArrayLayers;
|
||||
imageInfo.mipLevels = 1;
|
||||
imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
|
||||
DxvkImageViewCreateInfo viewInfo;
|
||||
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewInfo.format = fmt.format;
|
||||
viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewInfo.minLevel = 0;
|
||||
viewInfo.numLevels = 1;
|
||||
viewInfo.minLayer = 0;
|
||||
viewInfo.numLayers = swapInfo.imageArrayLayers;
|
||||
|
||||
Rc<DxvkImage> image = new DxvkImage(m_vkd, imageInfo, swapImages.at(i));
|
||||
Rc<DxvkImageView> iview = m_device->createImageView(image, viewInfo);
|
||||
|
||||
|
@ -16,7 +16,7 @@ dxvk_src = files([
|
||||
'dxvk_lifetime.cpp',
|
||||
'dxvk_main.cpp',
|
||||
'dxvk_memory.cpp',
|
||||
'dxvk_pipemgr.cpp',
|
||||
'dxvk_pipeline.cpp',
|
||||
'dxvk_renderpass.cpp',
|
||||
'dxvk_resource.cpp',
|
||||
'dxvk_shader.cpp',
|
||||
|
@ -115,12 +115,12 @@ public:
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
SpirvCodeBuffer(_countof(fsCode), fsCode));
|
||||
|
||||
m_dxvkContext->bindShader(
|
||||
VK_SHADER_STAGE_VERTEX_BIT,
|
||||
m_dxvkVertexShader);
|
||||
m_dxvkContext->bindShader(
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
m_dxvkFragmentShader);
|
||||
m_dxvkBindingLayout = m_dxvkDevice->createBindingLayout(0, nullptr);
|
||||
|
||||
m_dxvkPipeline = m_dxvkDevice->createGraphicsPipeline(m_dxvkBindingLayout,
|
||||
m_dxvkVertexShader, nullptr, nullptr, nullptr, m_dxvkFragmentShader);
|
||||
|
||||
m_dxvkContext->bindGraphicsPipeline(m_dxvkPipeline);
|
||||
}
|
||||
|
||||
~TriangleApp() {
|
||||
@ -194,8 +194,10 @@ private:
|
||||
Rc<DxvkSwapchain> m_dxvkSwapchain;
|
||||
Rc<DxvkContext> m_dxvkContext;
|
||||
|
||||
Rc<DxvkShader> m_dxvkVertexShader;
|
||||
Rc<DxvkShader> m_dxvkFragmentShader;
|
||||
Rc<DxvkShader> m_dxvkVertexShader;
|
||||
Rc<DxvkShader> m_dxvkFragmentShader;
|
||||
Rc<DxvkBindingLayout> m_dxvkBindingLayout;
|
||||
Rc<DxvkGraphicsPipeline> m_dxvkPipeline;
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user