mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +01:00
[dxvk] Re-implemented pipeline creation within the backend
This commit is contained in:
parent
e95dc64c77
commit
19851c8432
@ -9,7 +9,7 @@ exe_wrapper = 'wine'
|
|||||||
c_args = ['-Og', '-ggdb']
|
c_args = ['-Og', '-ggdb']
|
||||||
c_link_args = ['-static', '-static-libgcc']
|
c_link_args = ['-static', '-static-libgcc']
|
||||||
|
|
||||||
cpp_args = ['-std=c++17', '-Og', '-ggdb']
|
cpp_args = ['-std=c++17', '-Og', '-gstabs']
|
||||||
cpp_link_args = ['-static', '-static-libgcc', '-static-libstdc++']
|
cpp_link_args = ['-static', '-static-libgcc', '-static-libstdc++']
|
||||||
|
|
||||||
[host_machine]
|
[host_machine]
|
||||||
|
@ -55,8 +55,6 @@ namespace dxvk {
|
|||||||
|
|
||||||
// Set up context state. The shader bindings and the
|
// Set up context state. The shader bindings and the
|
||||||
// constant state objects will never be modified.
|
// constant state objects will never be modified.
|
||||||
m_context->bindGraphicsPipeline(createPipeline());
|
|
||||||
|
|
||||||
m_context->setInputAssemblyState(
|
m_context->setInputAssemblyState(
|
||||||
new DxvkInputAssemblyState(
|
new DxvkInputAssemblyState(
|
||||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
|
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
|
||||||
@ -111,6 +109,14 @@ namespace dxvk {
|
|||||||
new DxvkBlendState(
|
new DxvkBlendState(
|
||||||
VK_FALSE, VK_LOGIC_OP_NO_OP,
|
VK_FALSE, VK_LOGIC_OP_NO_OP,
|
||||||
1, &blendAttachment));
|
1, &blendAttachment));
|
||||||
|
|
||||||
|
m_context->bindShader(
|
||||||
|
VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
this->createVertexShader());
|
||||||
|
|
||||||
|
m_context->bindShader(
|
||||||
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
this->createFragmentShader());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -329,7 +335,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
// Create the actual shader module
|
// Create the actual shader module
|
||||||
return m_device->createShader(
|
return m_device->createShader(
|
||||||
VK_SHADER_STAGE_VERTEX_BIT, module.compile());
|
VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
0, nullptr, module.compile());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -397,42 +404,24 @@ namespace dxvk {
|
|||||||
module.opReturn();
|
module.opReturn();
|
||||||
module.functionEnd();
|
module.functionEnd();
|
||||||
|
|
||||||
|
|
||||||
// Register function entry point
|
// Register function entry point
|
||||||
std::array<uint32_t, 2> interfaces = { inTexCoord, outColor };
|
std::array<uint32_t, 2> interfaces = { inTexCoord, outColor };
|
||||||
|
|
||||||
module.addEntryPoint(entryPointId, spv::ExecutionModelFragment,
|
module.addEntryPoint(entryPointId, spv::ExecutionModelFragment,
|
||||||
"main", interfaces.size(), interfaces.data());
|
"main", interfaces.size(), interfaces.data());
|
||||||
|
|
||||||
|
// Shader resource slots
|
||||||
|
std::array<DxvkResourceSlot, 2> resourceSlots = {{
|
||||||
|
{ BindingIds::Sampler, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||||
|
{ BindingIds::Texture, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||||
|
}};
|
||||||
|
|
||||||
// Create the actual shader module
|
// Create the actual shader module
|
||||||
return m_device->createShader(
|
return m_device->createShader(
|
||||||
VK_SHADER_STAGE_FRAGMENT_BIT, module.compile());
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
}
|
resourceSlots.size(),
|
||||||
|
resourceSlots.data(),
|
||||||
|
module.compile());
|
||||||
Rc<DxvkBindingLayout> DxgiPresenter::createBindingLayout() {
|
|
||||||
std::array<DxvkDescriptorSlot, 2> bindings;
|
|
||||||
bindings.at(BindingIds::Sampler).slot = BindingIds::Sampler;
|
|
||||||
bindings.at(BindingIds::Sampler).type = VK_DESCRIPTOR_TYPE_SAMPLER;
|
|
||||||
bindings.at(BindingIds::Sampler).stages = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
||||||
|
|
||||||
bindings.at(BindingIds::Texture).slot = BindingIds::Texture;
|
|
||||||
bindings.at(BindingIds::Texture).type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
|
||||||
bindings.at(BindingIds::Texture).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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -76,10 +76,6 @@ namespace dxvk {
|
|||||||
Rc<DxvkShader> createVertexShader();
|
Rc<DxvkShader> createVertexShader();
|
||||||
Rc<DxvkShader> createFragmentShader();
|
Rc<DxvkShader> createFragmentShader();
|
||||||
|
|
||||||
Rc<DxvkBindingLayout> createBindingLayout();
|
|
||||||
|
|
||||||
Rc<DxvkGraphicsPipeline> createPipeline();
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -336,6 +336,7 @@ namespace dxvk {
|
|||||||
DxvkImageCreateInfo imageInfo;
|
DxvkImageCreateInfo imageInfo;
|
||||||
imageInfo.type = VK_IMAGE_TYPE_2D;
|
imageInfo.type = VK_IMAGE_TYPE_2D;
|
||||||
imageInfo.format = bufferFormat.actual;
|
imageInfo.format = bufferFormat.actual;
|
||||||
|
imageInfo.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
|
||||||
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||||
imageInfo.extent.width = m_desc.BufferDesc.Width;
|
imageInfo.extent.width = m_desc.BufferDesc.Width;
|
||||||
imageInfo.extent.height = m_desc.BufferDesc.Height;
|
imageInfo.extent.height = m_desc.BufferDesc.Height;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "dxvk_descriptor.h"
|
#include "dxvk_descriptor.h"
|
||||||
#include "dxvk_lifetime.h"
|
#include "dxvk_lifetime.h"
|
||||||
#include "dxvk_pipeline.h"
|
#include "dxvk_pipelayout.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
|
@ -3,17 +3,36 @@
|
|||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
DxvkComputePipeline::DxvkComputePipeline(
|
DxvkComputePipeline::DxvkComputePipeline(
|
||||||
const Rc<vk::DeviceFn>& vkd,
|
const Rc<vk::DeviceFn>& vkd,
|
||||||
const Rc<DxvkBindingLayout>& layout,
|
const Rc<DxvkShader>& cs)
|
||||||
const Rc<DxvkShader>& cs)
|
: m_vkd(vkd) {
|
||||||
: m_vkd(vkd), m_layout(layout), m_cs(cs) {
|
DxvkDescriptorSlotMapping slotMapping;
|
||||||
|
cs->defineResourceSlots(slotMapping);
|
||||||
|
|
||||||
|
m_layout = new DxvkBindingLayout(vkd,
|
||||||
|
slotMapping.bindingCount(),
|
||||||
|
slotMapping.bindingInfos());
|
||||||
|
|
||||||
|
m_cs = cs->createShaderModule(slotMapping);
|
||||||
|
|
||||||
|
this->compilePipeline();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkComputePipeline::~DxvkComputePipeline() {
|
||||||
|
if (m_pipeline != VK_NULL_HANDLE)
|
||||||
|
m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipeline, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkComputePipeline::compilePipeline() {
|
||||||
std::vector<VkDescriptorSetLayoutBinding> bindings;
|
std::vector<VkDescriptorSetLayoutBinding> bindings;
|
||||||
|
|
||||||
VkComputePipelineCreateInfo info;
|
VkComputePipelineCreateInfo info;
|
||||||
info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
||||||
info.pNext = nullptr;
|
info.pNext = nullptr;
|
||||||
info.flags = 0;
|
info.flags = 0;
|
||||||
info.stage = cs->stageInfo();
|
info.stage = m_cs->stageInfo();
|
||||||
info.layout = m_layout->pipelineLayout();
|
info.layout = m_layout->pipelineLayout();
|
||||||
info.basePipelineHandle = VK_NULL_HANDLE;
|
info.basePipelineHandle = VK_NULL_HANDLE;
|
||||||
info.basePipelineIndex = 0;
|
info.basePipelineIndex = 0;
|
||||||
@ -23,10 +42,4 @@ namespace dxvk {
|
|||||||
throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to compile pipeline");
|
throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to compile pipeline");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DxvkComputePipeline::~DxvkComputePipeline() {
|
|
||||||
if (m_pipeline != VK_NULL_HANDLE)
|
|
||||||
m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipeline, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "dxvk_pipeline.h"
|
#include "dxvk_pipelayout.h"
|
||||||
#include "dxvk_resource.h"
|
#include "dxvk_resource.h"
|
||||||
#include "dxvk_shader.h"
|
#include "dxvk_shader.h"
|
||||||
|
|
||||||
@ -19,9 +19,8 @@ namespace dxvk {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
DxvkComputePipeline(
|
DxvkComputePipeline(
|
||||||
const Rc<vk::DeviceFn>& vkd,
|
const Rc<vk::DeviceFn>& vkd,
|
||||||
const Rc<DxvkBindingLayout>& layout,
|
const Rc<DxvkShader>& cs);
|
||||||
const Rc<DxvkShader>& cs);
|
|
||||||
~DxvkComputePipeline();
|
~DxvkComputePipeline();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,10 +47,12 @@ namespace dxvk {
|
|||||||
|
|
||||||
Rc<vk::DeviceFn> m_vkd;
|
Rc<vk::DeviceFn> m_vkd;
|
||||||
Rc<DxvkBindingLayout> m_layout;
|
Rc<DxvkBindingLayout> m_layout;
|
||||||
Rc<DxvkShader> m_cs;
|
Rc<DxvkShaderModule> m_cs;
|
||||||
|
|
||||||
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
void compilePipeline();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -53,32 +53,6 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::bindComputePipeline(
|
|
||||||
const Rc<DxvkComputePipeline>& pipeline) {
|
|
||||||
if (m_state.cPipe != pipeline) {
|
|
||||||
m_state.cPipe = pipeline;
|
|
||||||
|
|
||||||
m_flags.set(
|
|
||||||
DxvkContextFlag::CpDirtyPipeline,
|
|
||||||
DxvkContextFlag::CpDirtyResources);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::bindGraphicsPipeline(
|
|
||||||
const Rc<DxvkGraphicsPipeline>& pipeline) {
|
|
||||||
if (m_state.gPipe != pipeline) {
|
|
||||||
m_state.gPipe = pipeline;
|
|
||||||
|
|
||||||
m_flags.set(
|
|
||||||
DxvkContextFlag::GpDirtyPipeline,
|
|
||||||
DxvkContextFlag::GpDirtyResources,
|
|
||||||
DxvkContextFlag::GpDirtyVertexBuffers,
|
|
||||||
DxvkContextFlag::GpDirtyIndexBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::bindIndexBuffer(
|
void DxvkContext::bindIndexBuffer(
|
||||||
const DxvkBufferBinding& buffer) {
|
const DxvkBufferBinding& buffer) {
|
||||||
if (m_state.vi.indexBuffer != buffer) {
|
if (m_state.vi.indexBuffer != buffer) {
|
||||||
@ -178,6 +152,31 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::bindShader(
|
||||||
|
VkShaderStageFlagBits stage,
|
||||||
|
const Rc<DxvkShader>& shader) {
|
||||||
|
DxvkShaderStage* shaderStage = nullptr;
|
||||||
|
|
||||||
|
switch (stage) {
|
||||||
|
case VK_SHADER_STAGE_VERTEX_BIT: shaderStage = &m_state.gp.vs; break;
|
||||||
|
case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: shaderStage = &m_state.gp.tcs; break;
|
||||||
|
case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: shaderStage = &m_state.gp.tes; break;
|
||||||
|
case VK_SHADER_STAGE_GEOMETRY_BIT: shaderStage = &m_state.gp.gs; break;
|
||||||
|
case VK_SHADER_STAGE_FRAGMENT_BIT: shaderStage = &m_state.gp.fs; break;
|
||||||
|
case VK_SHADER_STAGE_COMPUTE_BIT: shaderStage = &m_state.cp.cs; break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shaderStage->shader != shader) {
|
||||||
|
shaderStage->shader = shader;
|
||||||
|
|
||||||
|
m_flags.set(stage == VK_SHADER_STAGE_COMPUTE_BIT
|
||||||
|
? DxvkContextFlag::CpDirtyPipeline
|
||||||
|
: DxvkContextFlag::GpDirtyPipeline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::bindVertexBuffer(
|
void DxvkContext::bindVertexBuffer(
|
||||||
uint32_t binding,
|
uint32_t binding,
|
||||||
const DxvkBufferBinding& buffer) {
|
const DxvkBufferBinding& buffer) {
|
||||||
@ -445,9 +444,12 @@ namespace dxvk {
|
|||||||
if (m_flags.test(DxvkContextFlag::CpDirtyPipeline)) {
|
if (m_flags.test(DxvkContextFlag::CpDirtyPipeline)) {
|
||||||
m_flags.clr(DxvkContextFlag::CpDirtyPipeline);
|
m_flags.clr(DxvkContextFlag::CpDirtyPipeline);
|
||||||
|
|
||||||
|
m_state.cp.pipeline = m_device->createComputePipeline(
|
||||||
|
m_state.cp.cs.shader);
|
||||||
|
|
||||||
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE,
|
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||||
m_state.cPipe->getPipelineHandle());
|
m_state.cp.pipeline->getPipelineHandle());
|
||||||
m_cmd->trackResource(m_state.cPipe);
|
m_cmd->trackResource(m_state.cp.pipeline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,6 +458,10 @@ namespace dxvk {
|
|||||||
if (m_flags.test(DxvkContextFlag::GpDirtyPipeline)) {
|
if (m_flags.test(DxvkContextFlag::GpDirtyPipeline)) {
|
||||||
m_flags.clr(DxvkContextFlag::GpDirtyPipeline);
|
m_flags.clr(DxvkContextFlag::GpDirtyPipeline);
|
||||||
|
|
||||||
|
m_state.gp.pipeline = m_device->createGraphicsPipeline(
|
||||||
|
m_state.gp.vs.shader, m_state.gp.tcs.shader, m_state.gp.tes.shader,
|
||||||
|
m_state.gp.gs.shader, m_state.gp.fs.shader);
|
||||||
|
|
||||||
DxvkGraphicsPipelineStateInfo gpState;
|
DxvkGraphicsPipelineStateInfo gpState;
|
||||||
gpState.inputAssemblyState = m_state.co.inputAssemblyState;
|
gpState.inputAssemblyState = m_state.co.inputAssemblyState;
|
||||||
gpState.inputLayout = m_state.co.inputLayout;
|
gpState.inputLayout = m_state.co.inputLayout;
|
||||||
@ -467,8 +473,8 @@ namespace dxvk {
|
|||||||
gpState.viewportCount = m_state.vp.viewportCount;
|
gpState.viewportCount = m_state.vp.viewportCount;
|
||||||
|
|
||||||
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
m_state.gPipe->getPipelineHandle(gpState));
|
m_state.gp.pipeline->getPipelineHandle(gpState));
|
||||||
m_cmd->trackResource(m_state.gPipe);
|
m_cmd->trackResource(m_state.gp.pipeline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,7 +483,7 @@ namespace dxvk {
|
|||||||
if (m_flags.test(DxvkContextFlag::CpDirtyResources)) {
|
if (m_flags.test(DxvkContextFlag::CpDirtyResources)) {
|
||||||
m_flags.clr(DxvkContextFlag::CpDirtyResources);
|
m_flags.clr(DxvkContextFlag::CpDirtyResources);
|
||||||
|
|
||||||
auto layout = m_state.cPipe->layout();
|
auto layout = m_state.cp.pipeline->layout();
|
||||||
|
|
||||||
m_cmd->bindResourceDescriptors(
|
m_cmd->bindResourceDescriptors(
|
||||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||||
@ -494,7 +500,7 @@ namespace dxvk {
|
|||||||
if (m_flags.test(DxvkContextFlag::GpDirtyResources)) {
|
if (m_flags.test(DxvkContextFlag::GpDirtyResources)) {
|
||||||
m_flags.clr(DxvkContextFlag::GpDirtyResources);
|
m_flags.clr(DxvkContextFlag::GpDirtyResources);
|
||||||
|
|
||||||
auto layout = m_state.gPipe->layout();
|
auto layout = m_state.gp.pipeline->layout();
|
||||||
|
|
||||||
m_cmd->bindResourceDescriptors(
|
m_cmd->bindResourceDescriptors(
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
@ -54,20 +54,6 @@ namespace dxvk {
|
|||||||
void bindFramebuffer(
|
void bindFramebuffer(
|
||||||
const Rc<DxvkFramebuffer>& fb);
|
const Rc<DxvkFramebuffer>& fb);
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Binds compute pipeline
|
|
||||||
* \param [in] pipeline The pipeline to bind
|
|
||||||
*/
|
|
||||||
void bindComputePipeline(
|
|
||||||
const Rc<DxvkComputePipeline>& pipeline);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Binds graphics pipeline
|
|
||||||
* \param [in] pipeline The pipeline to bind
|
|
||||||
*/
|
|
||||||
void bindGraphicsPipeline(
|
|
||||||
const Rc<DxvkGraphicsPipeline>& pipeline);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Binds index buffer
|
* \brief Binds index buffer
|
||||||
*
|
*
|
||||||
@ -133,6 +119,16 @@ namespace dxvk {
|
|||||||
uint32_t slot,
|
uint32_t slot,
|
||||||
const Rc<DxvkSampler>& sampler);
|
const Rc<DxvkSampler>& sampler);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Binds a shader to a given state
|
||||||
|
*
|
||||||
|
* \param [in] stage Target shader stage
|
||||||
|
* \param [in] shader The shader to bind
|
||||||
|
*/
|
||||||
|
void bindShader(
|
||||||
|
VkShaderStageFlagBits stage,
|
||||||
|
const Rc<DxvkShader>& shader);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Binds vertex buffer
|
* \brief Binds vertex buffer
|
||||||
*
|
*
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "dxvk_graphics.h"
|
#include "dxvk_graphics.h"
|
||||||
#include "dxvk_image.h"
|
#include "dxvk_image.h"
|
||||||
#include "dxvk_limits.h"
|
#include "dxvk_limits.h"
|
||||||
#include "dxvk_pipeline.h"
|
#include "dxvk_pipelayout.h"
|
||||||
#include "dxvk_sampler.h"
|
#include "dxvk_sampler.h"
|
||||||
#include "dxvk_shader.h"
|
#include "dxvk_shader.h"
|
||||||
|
|
||||||
@ -54,6 +54,28 @@ namespace dxvk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct DxvkShaderStage {
|
||||||
|
Rc<DxvkShader> shader;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct DxvkGraphicsPipelineState {
|
||||||
|
DxvkShaderStage vs;
|
||||||
|
DxvkShaderStage tcs;
|
||||||
|
DxvkShaderStage tes;
|
||||||
|
DxvkShaderStage gs;
|
||||||
|
DxvkShaderStage fs;
|
||||||
|
|
||||||
|
Rc<DxvkGraphicsPipeline> pipeline;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct DxvkComputePipelineState {
|
||||||
|
DxvkShaderStage cs;
|
||||||
|
Rc<DxvkComputePipeline> pipeline;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Pipeline state
|
* \brief Pipeline state
|
||||||
*
|
*
|
||||||
@ -66,8 +88,8 @@ namespace dxvk {
|
|||||||
DxvkOutputMergerState om;
|
DxvkOutputMergerState om;
|
||||||
DxvkConstantStateObjects co;
|
DxvkConstantStateObjects co;
|
||||||
|
|
||||||
Rc<DxvkGraphicsPipeline> gPipe;
|
DxvkGraphicsPipelineState gp;
|
||||||
Rc<DxvkComputePipeline> cPipe;
|
DxvkComputePipelineState cp;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -11,7 +11,8 @@ namespace dxvk {
|
|||||||
m_vkd (vkd),
|
m_vkd (vkd),
|
||||||
m_features (features),
|
m_features (features),
|
||||||
m_memory (new DxvkMemoryAllocator(adapter, vkd)),
|
m_memory (new DxvkMemoryAllocator(adapter, vkd)),
|
||||||
m_renderPassPool (new DxvkRenderPassPool (vkd)) {
|
m_renderPassPool (new DxvkRenderPassPool (vkd)),
|
||||||
|
m_pipelineManager (new DxvkPipelineManager(vkd)) {
|
||||||
m_vkd->vkGetDeviceQueue(m_vkd->device(),
|
m_vkd->vkGetDeviceQueue(m_vkd->device(),
|
||||||
m_adapter->graphicsQueueFamily(), 0,
|
m_adapter->graphicsQueueFamily(), 0,
|
||||||
&m_graphicsQueue);
|
&m_graphicsQueue);
|
||||||
@ -23,6 +24,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
DxvkDevice::~DxvkDevice() {
|
DxvkDevice::~DxvkDevice() {
|
||||||
m_renderPassPool = nullptr;
|
m_renderPassPool = nullptr;
|
||||||
|
m_pipelineManager = nullptr;
|
||||||
m_memory = nullptr;
|
m_memory = nullptr;
|
||||||
|
|
||||||
m_vkd->vkDeviceWaitIdle(m_vkd->device());
|
m_vkd->vkDeviceWaitIdle(m_vkd->device());
|
||||||
@ -92,34 +94,27 @@ namespace dxvk {
|
|||||||
|
|
||||||
Rc<DxvkShader> DxvkDevice::createShader(
|
Rc<DxvkShader> DxvkDevice::createShader(
|
||||||
VkShaderStageFlagBits stage,
|
VkShaderStageFlagBits stage,
|
||||||
|
uint32_t slotCount,
|
||||||
|
const DxvkResourceSlot* slotInfos,
|
||||||
const SpirvCodeBuffer& code) {
|
const SpirvCodeBuffer& code) {
|
||||||
return new DxvkShader(m_vkd, stage, code);
|
return new DxvkShader(m_vkd, stage,
|
||||||
}
|
slotCount, slotInfos, code);
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkBindingLayout> DxvkDevice::createBindingLayout(
|
|
||||||
uint32_t bindingCount,
|
|
||||||
const DxvkDescriptorSlot* bindingInfos) {
|
|
||||||
return new DxvkBindingLayout(m_vkd, bindingCount, bindingInfos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkComputePipeline> DxvkDevice::createComputePipeline(
|
Rc<DxvkComputePipeline> DxvkDevice::createComputePipeline(
|
||||||
const Rc<DxvkBindingLayout>& layout,
|
const Rc<DxvkShader>& cs) {
|
||||||
const Rc<DxvkShader>& cs) {
|
return m_pipelineManager->createComputePipeline(cs);
|
||||||
return new DxvkComputePipeline(m_vkd, layout, cs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkGraphicsPipeline> DxvkDevice::createGraphicsPipeline(
|
Rc<DxvkGraphicsPipeline> DxvkDevice::createGraphicsPipeline(
|
||||||
const Rc<DxvkBindingLayout>& layout,
|
const Rc<DxvkShader>& vs,
|
||||||
const Rc<DxvkShader>& vs,
|
const Rc<DxvkShader>& tcs,
|
||||||
const Rc<DxvkShader>& tcs,
|
const Rc<DxvkShader>& tes,
|
||||||
const Rc<DxvkShader>& tes,
|
const Rc<DxvkShader>& gs,
|
||||||
const Rc<DxvkShader>& gs,
|
const Rc<DxvkShader>& fs) {
|
||||||
const Rc<DxvkShader>& fs) {
|
return m_pipelineManager->createGraphicsPipeline(vs, tcs, tes, gs, fs);
|
||||||
return new DxvkGraphicsPipeline(m_vkd,
|
|
||||||
layout, vs, tcs, tes, gs, fs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "dxvk_framebuffer.h"
|
#include "dxvk_framebuffer.h"
|
||||||
#include "dxvk_image.h"
|
#include "dxvk_image.h"
|
||||||
#include "dxvk_memory.h"
|
#include "dxvk_memory.h"
|
||||||
|
#include "dxvk_pipemanager.h"
|
||||||
#include "dxvk_renderpass.h"
|
#include "dxvk_renderpass.h"
|
||||||
#include "dxvk_sampler.h"
|
#include "dxvk_sampler.h"
|
||||||
#include "dxvk_shader.h"
|
#include "dxvk_shader.h"
|
||||||
@ -166,48 +167,36 @@ namespace dxvk {
|
|||||||
*/
|
*/
|
||||||
Rc<DxvkShader> createShader(
|
Rc<DxvkShader> createShader(
|
||||||
VkShaderStageFlagBits stage,
|
VkShaderStageFlagBits stage,
|
||||||
|
uint32_t slotCount,
|
||||||
|
const DxvkResourceSlot* slotInfos,
|
||||||
const SpirvCodeBuffer& code);
|
const SpirvCodeBuffer& code);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Creates binding layout
|
* \brief Retrieves a compute pipeline
|
||||||
*
|
|
||||||
* \param [in] bindingCount Number of bindings
|
|
||||||
* \param [in] bindingInfos Binding descriptions
|
|
||||||
* \returns New binding layout
|
|
||||||
*/
|
|
||||||
Rc<DxvkBindingLayout> createBindingLayout(
|
|
||||||
uint32_t bindingCount,
|
|
||||||
const DxvkDescriptorSlot* bindingInfos);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Creates a compute pipeline
|
|
||||||
*
|
*
|
||||||
* \param [in] layout Pipeline binding layout
|
* \param [in] layout Pipeline binding layout
|
||||||
* \param [in] cs Compute shader
|
* \param [in] cs Compute shader
|
||||||
* \returns New compute pipeline
|
* \returns The compute pipeline
|
||||||
*/
|
*/
|
||||||
Rc<DxvkComputePipeline> createComputePipeline(
|
Rc<DxvkComputePipeline> createComputePipeline(
|
||||||
const Rc<DxvkBindingLayout>& layout,
|
const Rc<DxvkShader>& cs);
|
||||||
const Rc<DxvkShader>& cs);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Creates a graphics pipeline
|
* \brief Retrieves a graphics pipeline object
|
||||||
*
|
*
|
||||||
* \param [in] layout Pipeline binding layout
|
|
||||||
* \param [in] vs Vertex shader
|
* \param [in] vs Vertex shader
|
||||||
* \param [in] tcs Tessellation control shader
|
* \param [in] tcs Tessellation control shader
|
||||||
* \param [in] tes Tessellation evaluation shader
|
* \param [in] tes Tessellation evaluation shader
|
||||||
* \param [in] gs Geometry shader
|
* \param [in] gs Geometry shader
|
||||||
* \param [in] fs Fragment shader
|
* \param [in] fs Fragment shader
|
||||||
* \returns New graphics pipeline
|
* \returns The graphics pipeline
|
||||||
*/
|
*/
|
||||||
Rc<DxvkGraphicsPipeline> createGraphicsPipeline(
|
Rc<DxvkGraphicsPipeline> createGraphicsPipeline(
|
||||||
const Rc<DxvkBindingLayout>& layout,
|
const Rc<DxvkShader>& vs,
|
||||||
const Rc<DxvkShader>& vs,
|
const Rc<DxvkShader>& tcs,
|
||||||
const Rc<DxvkShader>& tcs,
|
const Rc<DxvkShader>& tes,
|
||||||
const Rc<DxvkShader>& tes,
|
const Rc<DxvkShader>& gs,
|
||||||
const Rc<DxvkShader>& gs,
|
const Rc<DxvkShader>& fs);
|
||||||
const Rc<DxvkShader>& fs);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Creates a swap chain
|
* \brief Creates a swap chain
|
||||||
@ -252,6 +241,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
Rc<DxvkMemoryAllocator> m_memory;
|
Rc<DxvkMemoryAllocator> m_memory;
|
||||||
Rc<DxvkRenderPassPool> m_renderPassPool;
|
Rc<DxvkRenderPassPool> m_renderPassPool;
|
||||||
|
Rc<DxvkPipelineManager> m_pipelineManager;
|
||||||
|
|
||||||
VkQueue m_graphicsQueue;
|
VkQueue m_graphicsQueue;
|
||||||
VkQueue m_presentQueue;
|
VkQueue m_presentQueue;
|
||||||
|
@ -39,16 +39,29 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
DxvkGraphicsPipeline::DxvkGraphicsPipeline(
|
DxvkGraphicsPipeline::DxvkGraphicsPipeline(
|
||||||
const Rc<vk::DeviceFn>& vkd,
|
const Rc<vk::DeviceFn>& vkd,
|
||||||
const Rc<DxvkBindingLayout>& layout,
|
const Rc<DxvkShader>& vs,
|
||||||
const Rc<DxvkShader>& vs,
|
const Rc<DxvkShader>& tcs,
|
||||||
const Rc<DxvkShader>& tcs,
|
const Rc<DxvkShader>& tes,
|
||||||
const Rc<DxvkShader>& tes,
|
const Rc<DxvkShader>& gs,
|
||||||
const Rc<DxvkShader>& gs,
|
const Rc<DxvkShader>& fs)
|
||||||
const Rc<DxvkShader>& fs)
|
: m_vkd(vkd) {
|
||||||
: m_vkd(vkd), m_layout(layout),
|
DxvkDescriptorSlotMapping slotMapping;
|
||||||
m_vs(vs), m_tcs(tcs), m_tes(tes), m_gs(gs), m_fs(fs) {
|
if (vs != nullptr) vs ->defineResourceSlots(slotMapping);
|
||||||
|
if (tcs != nullptr) tcs->defineResourceSlots(slotMapping);
|
||||||
|
if (tes != nullptr) tes->defineResourceSlots(slotMapping);
|
||||||
|
if (gs != nullptr) gs ->defineResourceSlots(slotMapping);
|
||||||
|
if (fs != nullptr) fs ->defineResourceSlots(slotMapping);
|
||||||
|
|
||||||
|
m_layout = new DxvkBindingLayout(vkd,
|
||||||
|
slotMapping.bindingCount(),
|
||||||
|
slotMapping.bindingInfos());
|
||||||
|
|
||||||
|
if (vs != nullptr) m_vs = vs ->createShaderModule(slotMapping);
|
||||||
|
if (tcs != nullptr) m_tcs = tcs->createShaderModule(slotMapping);
|
||||||
|
if (tes != nullptr) m_tes = tes->createShaderModule(slotMapping);
|
||||||
|
if (gs != nullptr) m_gs = gs ->createShaderModule(slotMapping);
|
||||||
|
if (fs != nullptr) m_fs = fs ->createShaderModule(slotMapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "dxvk_constant_state.h"
|
#include "dxvk_constant_state.h"
|
||||||
#include "dxvk_hash.h"
|
#include "dxvk_hash.h"
|
||||||
#include "dxvk_pipeline.h"
|
#include "dxvk_pipelayout.h"
|
||||||
#include "dxvk_resource.h"
|
#include "dxvk_resource.h"
|
||||||
#include "dxvk_shader.h"
|
#include "dxvk_shader.h"
|
||||||
|
|
||||||
@ -49,13 +49,12 @@ namespace dxvk {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
DxvkGraphicsPipeline(
|
DxvkGraphicsPipeline(
|
||||||
const Rc<vk::DeviceFn>& vkd,
|
const Rc<vk::DeviceFn>& vkd,
|
||||||
const Rc<DxvkBindingLayout>& layout,
|
const Rc<DxvkShader>& vs,
|
||||||
const Rc<DxvkShader>& vs,
|
const Rc<DxvkShader>& tcs,
|
||||||
const Rc<DxvkShader>& tcs,
|
const Rc<DxvkShader>& tes,
|
||||||
const Rc<DxvkShader>& tes,
|
const Rc<DxvkShader>& gs,
|
||||||
const Rc<DxvkShader>& gs,
|
const Rc<DxvkShader>& fs);
|
||||||
const Rc<DxvkShader>& fs);
|
|
||||||
~DxvkGraphicsPipeline();
|
~DxvkGraphicsPipeline();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,11 +81,11 @@ namespace dxvk {
|
|||||||
Rc<vk::DeviceFn> m_vkd;
|
Rc<vk::DeviceFn> m_vkd;
|
||||||
Rc<DxvkBindingLayout> m_layout;
|
Rc<DxvkBindingLayout> m_layout;
|
||||||
|
|
||||||
Rc<DxvkShader> m_vs;
|
Rc<DxvkShaderModule> m_vs;
|
||||||
Rc<DxvkShader> m_tcs;
|
Rc<DxvkShaderModule> m_tcs;
|
||||||
Rc<DxvkShader> m_tes;
|
Rc<DxvkShaderModule> m_tes;
|
||||||
Rc<DxvkShader> m_gs;
|
Rc<DxvkShaderModule> m_gs;
|
||||||
Rc<DxvkShader> m_fs;
|
Rc<DxvkShaderModule> m_fs;
|
||||||
|
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
|
|
||||||
|
@ -1,9 +1,44 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "dxvk_pipeline.h"
|
#include "dxvk_pipelayout.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
|
DxvkDescriptorSlotMapping:: DxvkDescriptorSlotMapping() { }
|
||||||
|
DxvkDescriptorSlotMapping::~DxvkDescriptorSlotMapping() { }
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkDescriptorSlotMapping::defineSlot(
|
||||||
|
uint32_t slot,
|
||||||
|
VkDescriptorType type,
|
||||||
|
VkShaderStageFlagBits stage) {
|
||||||
|
uint32_t bindingId = this->getBindingId(slot);
|
||||||
|
|
||||||
|
if (bindingId != InvalidBinding) {
|
||||||
|
m_descriptorSlots.at(bindingId).stages |= stage;
|
||||||
|
} else {
|
||||||
|
DxvkDescriptorSlot slotInfo;
|
||||||
|
slotInfo.slot = slot;
|
||||||
|
slotInfo.type = type;
|
||||||
|
slotInfo.stages = stage;
|
||||||
|
m_descriptorSlots.push_back(slotInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t DxvkDescriptorSlotMapping::getBindingId(uint32_t slot) {
|
||||||
|
// This won't win a performance competition, but the number
|
||||||
|
// of bindings used by a shader is usually much smaller than
|
||||||
|
// the number of resource slots available to the system.
|
||||||
|
for (uint32_t i = 0; i < m_descriptorSlots.size(); i++) {
|
||||||
|
if (m_descriptorSlots.at(i).slot == slot)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return InvalidBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DxvkBindingLayout::DxvkBindingLayout(
|
DxvkBindingLayout::DxvkBindingLayout(
|
||||||
const Rc<vk::DeviceFn>& vkd,
|
const Rc<vk::DeviceFn>& vkd,
|
||||||
uint32_t bindingCount,
|
uint32_t bindingCount,
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "dxvk_include.h"
|
#include "dxvk_include.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
@ -18,6 +20,69 @@ namespace dxvk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Descriptor slot mapping
|
||||||
|
*
|
||||||
|
* Convenience class that generates descriptor slot
|
||||||
|
* index to binding index mappings. This is required
|
||||||
|
* when generating Vulkan pipeline and descriptor set
|
||||||
|
* layouts.
|
||||||
|
*/
|
||||||
|
class DxvkDescriptorSlotMapping {
|
||||||
|
constexpr static uint32_t InvalidBinding = 0xFFFFFFFFu;
|
||||||
|
public:
|
||||||
|
|
||||||
|
DxvkDescriptorSlotMapping();
|
||||||
|
~DxvkDescriptorSlotMapping();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Number of descriptor bindings
|
||||||
|
* \returns Descriptor binding count
|
||||||
|
*/
|
||||||
|
uint32_t bindingCount() const {
|
||||||
|
return m_descriptorSlots.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Descriptor binding infos
|
||||||
|
* \returns Descriptor binding infos
|
||||||
|
*/
|
||||||
|
const DxvkDescriptorSlot* bindingInfos() const {
|
||||||
|
return m_descriptorSlots.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Defines a new slot
|
||||||
|
*
|
||||||
|
* Adds a slot to the mapping. If the slot is already
|
||||||
|
* defined by another shader stage, this will extend
|
||||||
|
* the stage mask by the given stage. Otherwise, an
|
||||||
|
* entirely new binding is added.
|
||||||
|
* \param [in] slot Resource slot
|
||||||
|
* \param [in] type Resource type
|
||||||
|
* \param [in] stage Shader stage
|
||||||
|
*/
|
||||||
|
void defineSlot(
|
||||||
|
uint32_t slot,
|
||||||
|
VkDescriptorType type,
|
||||||
|
VkShaderStageFlagBits stage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Gets binding ID for a slot
|
||||||
|
*
|
||||||
|
* \param [in] slot Resource slot
|
||||||
|
* \returns Binding index, or \c InvalidBinding
|
||||||
|
*/
|
||||||
|
uint32_t getBindingId(
|
||||||
|
uint32_t slot);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::vector<DxvkDescriptorSlot> m_descriptorSlots;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Shader interface
|
* \brief Shader interface
|
||||||
*
|
*
|
96
src/dxvk/dxvk_pipemanager.cpp
Normal file
96
src/dxvk/dxvk_pipemanager.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#include "dxvk_pipemanager.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
size_t DxvkPipelineKeyHash::operator () (const DxvkComputePipelineKey& key) const {
|
||||||
|
std::hash<DxvkShader*> hash;
|
||||||
|
return hash(key.cs.ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t DxvkPipelineKeyHash::operator () (const DxvkGraphicsPipelineKey& key) const {
|
||||||
|
DxvkHashState state;
|
||||||
|
|
||||||
|
std::hash<DxvkShader*> hash;
|
||||||
|
state.add(hash(key.vs.ptr()));
|
||||||
|
state.add(hash(key.tcs.ptr()));
|
||||||
|
state.add(hash(key.tes.ptr()));
|
||||||
|
state.add(hash(key.gs.ptr()));
|
||||||
|
state.add(hash(key.fs.ptr()));
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DxvkPipelineKeyEq::operator () (const DxvkComputePipelineKey& a, const DxvkComputePipelineKey& b) const {
|
||||||
|
return a.cs == b.cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DxvkPipelineKeyEq::operator () (const DxvkGraphicsPipelineKey& a, const DxvkGraphicsPipelineKey& b) const {
|
||||||
|
return a.vs == b.vs
|
||||||
|
&& a.tcs == b.tcs
|
||||||
|
&& a.tes == b.tes
|
||||||
|
&& a.gs == b.gs
|
||||||
|
&& a.fs == b.fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkPipelineManager::DxvkPipelineManager(const Rc<vk::DeviceFn>& vkd)
|
||||||
|
: m_vkd(vkd) { }
|
||||||
|
|
||||||
|
|
||||||
|
DxvkPipelineManager::~DxvkPipelineManager() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rc<DxvkComputePipeline> DxvkPipelineManager::createComputePipeline(
|
||||||
|
const Rc<DxvkShader>& cs) {
|
||||||
|
if (cs == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
DxvkComputePipelineKey key;
|
||||||
|
key.cs = cs;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
auto pair = m_computePipelines.find(key);
|
||||||
|
|
||||||
|
if (pair != m_computePipelines.end())
|
||||||
|
return pair->second;
|
||||||
|
|
||||||
|
const Rc<DxvkComputePipeline> pipeline
|
||||||
|
= new DxvkComputePipeline(m_vkd, cs);
|
||||||
|
m_computePipelines.insert(std::make_pair(key, pipeline));
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rc<DxvkGraphicsPipeline> DxvkPipelineManager::createGraphicsPipeline(
|
||||||
|
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;
|
||||||
|
|
||||||
|
DxvkGraphicsPipelineKey key;
|
||||||
|
key.vs = vs;
|
||||||
|
key.tcs = tcs;
|
||||||
|
key.tes = tes;
|
||||||
|
key.gs = gs;
|
||||||
|
key.fs = fs;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
auto pair = m_graphicsPipelines.find(key);
|
||||||
|
|
||||||
|
if (pair != m_graphicsPipelines.end())
|
||||||
|
return pair->second;
|
||||||
|
|
||||||
|
const Rc<DxvkGraphicsPipeline> pipeline
|
||||||
|
= new DxvkGraphicsPipeline(m_vkd, vs, tcs, tes, gs, fs);
|
||||||
|
m_graphicsPipelines.insert(std::make_pair(key, pipeline));
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
118
src/dxvk/dxvk_pipemanager.h
Normal file
118
src/dxvk/dxvk_pipemanager.h
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "dxvk_compute.h"
|
||||||
|
#include "dxvk_graphics.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compute pipeline key
|
||||||
|
*
|
||||||
|
* Identifier for a compute pipeline object.
|
||||||
|
* Consists of the compute shader itself.
|
||||||
|
*/
|
||||||
|
struct DxvkComputePipelineKey {
|
||||||
|
Rc<DxvkShader> cs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Graphics pipeline key
|
||||||
|
*
|
||||||
|
* Identifier for a graphics pipeline object.
|
||||||
|
* Consists of all graphics pipeline shaders.
|
||||||
|
*/
|
||||||
|
struct DxvkGraphicsPipelineKey {
|
||||||
|
Rc<DxvkShader> vs;
|
||||||
|
Rc<DxvkShader> tcs;
|
||||||
|
Rc<DxvkShader> tes;
|
||||||
|
Rc<DxvkShader> gs;
|
||||||
|
Rc<DxvkShader> fs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct DxvkPipelineKeyHash {
|
||||||
|
size_t operator () (const DxvkComputePipelineKey& key) const;
|
||||||
|
size_t operator () (const DxvkGraphicsPipelineKey& key) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct DxvkPipelineKeyEq {
|
||||||
|
bool operator () (const DxvkComputePipelineKey& a, const DxvkComputePipelineKey& b) const;
|
||||||
|
bool operator () (const DxvkGraphicsPipelineKey& a, const DxvkGraphicsPipelineKey& b) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Pipeline manager
|
||||||
|
*
|
||||||
|
* Creates and stores graphics pipelines and compute
|
||||||
|
* pipelines for each combination of shaders that is
|
||||||
|
* used within the application. This is necessary
|
||||||
|
* because DXVK does not expose the concept of shader
|
||||||
|
* pipeline objects to the client API.
|
||||||
|
*/
|
||||||
|
class DxvkPipelineManager : public RcObject {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DxvkPipelineManager(
|
||||||
|
const Rc<vk::DeviceFn>& vkd);
|
||||||
|
~DxvkPipelineManager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieves a compute pipeline object
|
||||||
|
*
|
||||||
|
* If a pipeline for the given shader stage object
|
||||||
|
* already exists, it will be returned. Otherwise,
|
||||||
|
* a new pipeline will be created.
|
||||||
|
* \param [in] cs Compute shader
|
||||||
|
* \returns Compute pipeline object
|
||||||
|
*/
|
||||||
|
Rc<DxvkComputePipeline> createComputePipeline(
|
||||||
|
const Rc<DxvkShader>& cs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieves a graphics pipeline object
|
||||||
|
*
|
||||||
|
* If a pipeline for the given shader stage objects
|
||||||
|
* already exists, it will be returned. Otherwise,
|
||||||
|
* a new pipeline 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 object
|
||||||
|
*/
|
||||||
|
Rc<DxvkGraphicsPipeline> createGraphicsPipeline(
|
||||||
|
const Rc<DxvkShader>& vs,
|
||||||
|
const Rc<DxvkShader>& tcs,
|
||||||
|
const Rc<DxvkShader>& tes,
|
||||||
|
const Rc<DxvkShader>& gs,
|
||||||
|
const Rc<DxvkShader>& fs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const Rc<vk::DeviceFn> m_vkd;
|
||||||
|
|
||||||
|
std::mutex m_mutex;
|
||||||
|
|
||||||
|
std::unordered_map<
|
||||||
|
DxvkComputePipelineKey,
|
||||||
|
Rc<DxvkComputePipeline>,
|
||||||
|
DxvkPipelineKeyHash,
|
||||||
|
DxvkPipelineKeyEq> m_computePipelines;
|
||||||
|
|
||||||
|
std::unordered_map<
|
||||||
|
DxvkGraphicsPipelineKey,
|
||||||
|
Rc<DxvkGraphicsPipeline>,
|
||||||
|
DxvkPipelineKeyHash,
|
||||||
|
DxvkPipelineKeyEq> m_graphicsPipelines;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
DxvkShader::DxvkShader(
|
DxvkShaderModule::DxvkShaderModule(
|
||||||
const Rc<vk::DeviceFn>& vkd,
|
const Rc<vk::DeviceFn>& vkd,
|
||||||
VkShaderStageFlagBits stage,
|
VkShaderStageFlagBits stage,
|
||||||
const SpirvCodeBuffer& code)
|
const SpirvCodeBuffer& code)
|
||||||
@ -20,13 +20,13 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DxvkShader::~DxvkShader() {
|
DxvkShaderModule::~DxvkShaderModule() {
|
||||||
m_vkd->vkDestroyShaderModule(
|
m_vkd->vkDestroyShaderModule(
|
||||||
m_vkd->device(), m_module, nullptr);
|
m_vkd->device(), m_module, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VkPipelineShaderStageCreateInfo DxvkShader::stageInfo() const {
|
VkPipelineShaderStageCreateInfo DxvkShaderModule::stageInfo() const {
|
||||||
VkPipelineShaderStageCreateInfo info;
|
VkPipelineShaderStageCreateInfo info;
|
||||||
|
|
||||||
info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
@ -39,4 +39,35 @@ namespace dxvk {
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkShader::DxvkShader(
|
||||||
|
const Rc<vk::DeviceFn>& vkd,
|
||||||
|
VkShaderStageFlagBits stage,
|
||||||
|
uint32_t slotCount,
|
||||||
|
const DxvkResourceSlot* slotInfos,
|
||||||
|
const SpirvCodeBuffer& code)
|
||||||
|
: m_vkd(vkd), m_stage(stage), m_code(code) {
|
||||||
|
for (uint32_t i = 0; i < slotCount; i++)
|
||||||
|
m_slots.push_back(slotInfos[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkShader::~DxvkShader() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkShader::defineResourceSlots(
|
||||||
|
DxvkDescriptorSlotMapping& mapping) const {
|
||||||
|
for (const auto& slot : m_slots)
|
||||||
|
mapping.defineSlot(slot.slot, slot.type, m_stage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rc<DxvkShaderModule> DxvkShader::createShaderModule(
|
||||||
|
const DxvkDescriptorSlotMapping& mapping) const {
|
||||||
|
// TODO apply mapping
|
||||||
|
return new DxvkShaderModule(m_vkd, m_stage, m_code);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -3,6 +3,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "dxvk_include.h"
|
#include "dxvk_include.h"
|
||||||
|
#include "dxvk_pipelayout.h"
|
||||||
|
|
||||||
#include "../spirv/spirv_code_buffer.h"
|
#include "../spirv/spirv_code_buffer.h"
|
||||||
|
|
||||||
@ -15,30 +16,31 @@ namespace dxvk {
|
|||||||
* binding that a shader can access.
|
* binding that a shader can access.
|
||||||
*/
|
*/
|
||||||
struct DxvkResourceSlot {
|
struct DxvkResourceSlot {
|
||||||
uint32_t binding;
|
uint32_t slot;
|
||||||
VkDescriptorType type;
|
VkDescriptorType type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Shader module
|
* \brief Shader module object
|
||||||
*
|
*
|
||||||
* Manages a Vulkan shader module. This will not
|
* Manages a Vulkan shader module. This will not
|
||||||
* perform any sort of shader compilation. Instead,
|
* perform any shader compilation. Instead, the
|
||||||
* the context will create pipeline objects on the
|
* context will create pipeline objects on the
|
||||||
* fly when executing draw calls.
|
* fly when executing draw calls.
|
||||||
*/
|
*/
|
||||||
class DxvkShader : public RcObject {
|
class DxvkShaderModule : public RcObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DxvkShader(
|
DxvkShaderModule(
|
||||||
const Rc<vk::DeviceFn>& vkd,
|
const Rc<vk::DeviceFn>& vkd,
|
||||||
VkShaderStageFlagBits stage,
|
VkShaderStageFlagBits stage,
|
||||||
const SpirvCodeBuffer& code);
|
const SpirvCodeBuffer& code);
|
||||||
~DxvkShader();
|
|
||||||
|
|
||||||
VkShaderModule module() const {
|
~DxvkShaderModule();
|
||||||
|
|
||||||
|
VkShaderModule handle() const {
|
||||||
return m_module;
|
return m_module;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,4 +54,51 @@ namespace dxvk {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Shader object
|
||||||
|
*
|
||||||
|
* Stores a SPIR-V shader and information on the
|
||||||
|
* bindings that the shader uses. In order to use
|
||||||
|
* the shader with a pipeline, a shader module
|
||||||
|
* needs to be created from he shader object.
|
||||||
|
*/
|
||||||
|
class DxvkShader : public RcObject {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DxvkShader(
|
||||||
|
const Rc<vk::DeviceFn>& vkd,
|
||||||
|
VkShaderStageFlagBits stage,
|
||||||
|
uint32_t slotCount,
|
||||||
|
const DxvkResourceSlot* slotInfos,
|
||||||
|
const SpirvCodeBuffer& code);
|
||||||
|
~DxvkShader();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief
|
||||||
|
*/
|
||||||
|
void defineResourceSlots(
|
||||||
|
DxvkDescriptorSlotMapping& mapping) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Creates a shader module
|
||||||
|
*
|
||||||
|
* Maps the binding slot numbers
|
||||||
|
* \param [in] mapping Resource slot mapping
|
||||||
|
* \returns The shader module
|
||||||
|
*/
|
||||||
|
Rc<DxvkShaderModule> createShaderModule(
|
||||||
|
const DxvkDescriptorSlotMapping& mapping) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Rc<vk::DeviceFn> m_vkd;
|
||||||
|
VkShaderStageFlagBits m_stage;
|
||||||
|
SpirvCodeBuffer m_code;
|
||||||
|
|
||||||
|
std::vector<DxvkResourceSlot> m_slots;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -16,7 +16,8 @@ dxvk_src = files([
|
|||||||
'dxvk_lifetime.cpp',
|
'dxvk_lifetime.cpp',
|
||||||
'dxvk_main.cpp',
|
'dxvk_main.cpp',
|
||||||
'dxvk_memory.cpp',
|
'dxvk_memory.cpp',
|
||||||
'dxvk_pipeline.cpp',
|
'dxvk_pipelayout.cpp',
|
||||||
|
'dxvk_pipemanager.cpp',
|
||||||
'dxvk_renderpass.cpp',
|
'dxvk_renderpass.cpp',
|
||||||
'dxvk_resource.cpp',
|
'dxvk_resource.cpp',
|
||||||
'dxvk_sampler.cpp',
|
'dxvk_sampler.cpp',
|
||||||
|
@ -29,7 +29,7 @@ namespace dxvk {
|
|||||||
*/
|
*/
|
||||||
spv::Op opCode() const {
|
spv::Op opCode() const {
|
||||||
return static_cast<spv::Op>(
|
return static_cast<spv::Op>(
|
||||||
m_code[0] & spv::OpCodeMask);
|
this->arg(0) & spv::OpCodeMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,7 +37,7 @@ namespace dxvk {
|
|||||||
* \returns Number of DWORDs
|
* \returns Number of DWORDs
|
||||||
*/
|
*/
|
||||||
uint32_t length() const {
|
uint32_t length() const {
|
||||||
return m_code[0] >> spv::WordCountShift;
|
return this->arg(0) >> spv::WordCountShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,18 +113,12 @@ public:
|
|||||||
0, nullptr));
|
0, nullptr));
|
||||||
|
|
||||||
m_dxvkVertexShader = m_dxvkDevice->createShader(
|
m_dxvkVertexShader = m_dxvkDevice->createShader(
|
||||||
VK_SHADER_STAGE_VERTEX_BIT,
|
VK_SHADER_STAGE_VERTEX_BIT, 0, nullptr,
|
||||||
SpirvCodeBuffer(_countof(vsCode), vsCode));
|
SpirvCodeBuffer(_countof(vsCode), vsCode));
|
||||||
|
|
||||||
m_dxvkFragmentShader = m_dxvkDevice->createShader(
|
m_dxvkFragmentShader = m_dxvkDevice->createShader(
|
||||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
VK_SHADER_STAGE_FRAGMENT_BIT, 0, nullptr,
|
||||||
SpirvCodeBuffer(_countof(fsCode), fsCode));
|
SpirvCodeBuffer(_countof(fsCode), fsCode));
|
||||||
|
|
||||||
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() {
|
~TriangleApp() {
|
||||||
@ -158,6 +152,14 @@ public:
|
|||||||
|
|
||||||
m_dxvkContext->setViewports(1, &viewport, &scissor);
|
m_dxvkContext->setViewports(1, &viewport, &scissor);
|
||||||
|
|
||||||
|
m_dxvkContext->bindShader(
|
||||||
|
VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
m_dxvkVertexShader);
|
||||||
|
|
||||||
|
m_dxvkContext->bindShader(
|
||||||
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
m_dxvkFragmentShader);
|
||||||
|
|
||||||
VkClearAttachment clearAttachment;
|
VkClearAttachment clearAttachment;
|
||||||
clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
clearAttachment.colorAttachment = 0;
|
clearAttachment.colorAttachment = 0;
|
||||||
@ -198,10 +200,8 @@ private:
|
|||||||
Rc<DxvkSwapchain> m_dxvkSwapchain;
|
Rc<DxvkSwapchain> m_dxvkSwapchain;
|
||||||
Rc<DxvkContext> m_dxvkContext;
|
Rc<DxvkContext> m_dxvkContext;
|
||||||
|
|
||||||
Rc<DxvkShader> m_dxvkVertexShader;
|
Rc<DxvkShader> m_dxvkVertexShader;
|
||||||
Rc<DxvkShader> m_dxvkFragmentShader;
|
Rc<DxvkShader> m_dxvkFragmentShader;
|
||||||
Rc<DxvkBindingLayout> m_dxvkBindingLayout;
|
|
||||||
Rc<DxvkGraphicsPipeline> m_dxvkPipeline;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
lib_d3d11 = dxvk_compiler.find_library('d3d11')
|
lib_d3d11 = dxvk_compiler.find_library('d3d11')
|
||||||
lib_dxgi = dxvk_compiler.find_library('dxgi')
|
lib_dxgi = dxvk_compiler.find_library('dxgi')
|
||||||
lib_d3dcompiler_47 = dxvk_compiler.find_library('d3dcompiler_47')
|
lib_d3dcompiler_47 = dxvk_compiler.find_library('d3dcompiler')
|
||||||
|
|
||||||
subdir('d3d11')
|
subdir('d3d11')
|
||||||
subdir('dxbc')
|
subdir('dxbc')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user