mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-11-29 01:24:11 +01:00
[dxvk] Added shader stub, improved state tracking code
This commit is contained in:
parent
94af8140d2
commit
764220db98
17
src/dxvk/dxvk_compute.cpp
Normal file
17
src/dxvk/dxvk_compute.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "dxvk_compute.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkComputePipeline::DxvkComputePipeline(
|
||||
const Rc<vk::DeviceFn>& vkd)
|
||||
: m_vkd(vkd) {
|
||||
// TODO implement
|
||||
}
|
||||
|
||||
|
||||
DxvkComputePipeline::~DxvkComputePipeline() {
|
||||
m_vkd->vkDestroyPipeline(
|
||||
m_vkd->device(), m_pipeline, nullptr);
|
||||
}
|
||||
|
||||
}
|
34
src/dxvk/dxvk_compute.h
Normal file
34
src/dxvk/dxvk_compute.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxvk_shader.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Compute pipeline
|
||||
*
|
||||
* Stores a pipeline object
|
||||
*/
|
||||
class DxvkComputePipeline : public RcObject {
|
||||
|
||||
public:
|
||||
|
||||
DxvkComputePipeline(const Rc<vk::DeviceFn>& vkd);
|
||||
~DxvkComputePipeline();
|
||||
|
||||
/**
|
||||
* \brief Pipeline handle
|
||||
* \returns Pipeline handle
|
||||
*/
|
||||
VkPipeline handle() const {
|
||||
return m_pipeline;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
VkPipeline m_pipeline;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -19,13 +19,30 @@ namespace dxvk {
|
||||
TRACE(this, cmdList);
|
||||
m_commandList = cmdList;
|
||||
m_commandList->beginRecording();
|
||||
|
||||
// Make sure that we apply the current context state
|
||||
// to the command buffer when recording draw commands.
|
||||
m_state.g.flags.clr(
|
||||
DxvkGraphicsPipelineBit::RenderPassBound);
|
||||
m_state.g.flags.set(
|
||||
DxvkGraphicsPipelineBit::PipelineDirty,
|
||||
DxvkGraphicsPipelineBit::PipelineStateDirty,
|
||||
DxvkGraphicsPipelineBit::DirtyResources,
|
||||
DxvkGraphicsPipelineBit::DirtyVertexBuffers,
|
||||
DxvkGraphicsPipelineBit::DirtyIndexBuffer);
|
||||
|
||||
m_state.c.flags.set(
|
||||
DxvkComputePipelineBit::PipelineDirty,
|
||||
DxvkComputePipelineBit::DirtyResources);
|
||||
}
|
||||
|
||||
|
||||
bool DxvkContext::endRecording() {
|
||||
TRACE(this);
|
||||
|
||||
if (m_state.fb.flags.test(DxvkFbStateFlags::InsideRenderPass))
|
||||
// Any currently active render pass must be
|
||||
// ended before finalizing the command buffer.
|
||||
if (m_state.g.flags.test(DxvkGraphicsPipelineBit::RenderPassBound))
|
||||
this->endRenderPass();
|
||||
|
||||
// Finalize the command list
|
||||
@ -38,8 +55,7 @@ namespace dxvk {
|
||||
void DxvkContext::clearRenderTarget(
|
||||
const VkClearAttachment& attachment,
|
||||
const VkClearRect& clearArea) {
|
||||
if (!m_state.fb.flags.test(DxvkFbStateFlags::InsideRenderPass))
|
||||
this->beginRenderPass();
|
||||
this->flushGraphicsState();
|
||||
|
||||
m_vkd->vkCmdClearAttachments(
|
||||
m_commandList->handle(),
|
||||
@ -48,12 +64,25 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::dispatch(
|
||||
uint32_t wgCountX,
|
||||
uint32_t wgCountY,
|
||||
uint32_t wgCountZ) {
|
||||
this->flushComputeState();
|
||||
|
||||
m_vkd->vkCmdDispatch(
|
||||
m_commandList->handle(),
|
||||
wgCountX, wgCountY, wgCountZ);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::draw(
|
||||
uint32_t vertexCount,
|
||||
uint32_t instanceCount,
|
||||
uint32_t firstVertex,
|
||||
uint32_t firstInstance) {
|
||||
this->prepareDraw();
|
||||
this->flushGraphicsState();
|
||||
|
||||
m_vkd->vkCmdDraw(
|
||||
m_commandList->handle(),
|
||||
vertexCount,
|
||||
@ -69,7 +98,8 @@ namespace dxvk {
|
||||
uint32_t firstIndex,
|
||||
uint32_t vertexOffset,
|
||||
uint32_t firstInstance) {
|
||||
this->prepareDraw();
|
||||
this->flushGraphicsState();
|
||||
|
||||
m_vkd->vkCmdDrawIndexed(
|
||||
m_commandList->handle(),
|
||||
indexCount,
|
||||
@ -84,37 +114,57 @@ namespace dxvk {
|
||||
const Rc<DxvkFramebuffer>& fb) {
|
||||
TRACE(this, fb);
|
||||
|
||||
// When changing the framebuffer binding, we end the
|
||||
// current render pass, but beginning the new render
|
||||
// pass is deferred until a draw command is called.
|
||||
if (m_state.fb.framebuffer != fb) {
|
||||
if (m_state.fb.flags.test(DxvkFbStateFlags::InsideRenderPass))
|
||||
this->endRenderPass();
|
||||
if (m_state.g.fb != fb) {
|
||||
m_state.g.fb = fb;
|
||||
|
||||
m_state.fb.framebuffer = fb;
|
||||
m_commandList->trackResource(fb);
|
||||
if (m_state.g.flags.test(
|
||||
DxvkGraphicsPipelineBit::RenderPassBound))
|
||||
this->endRenderPass();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DxvkContext::setShader(
|
||||
VkShaderStageFlagBits stage,
|
||||
const Rc<DxvkShader>& shader) {
|
||||
TRACE(this, stage, shader);
|
||||
|
||||
DxvkShaderState* state = this->getShaderState(stage);
|
||||
|
||||
if (state->shader != shader) {
|
||||
state->shader = shader;
|
||||
|
||||
if (stage == VK_SHADER_STAGE_COMPUTE_BIT) {
|
||||
m_state.c.flags.set(
|
||||
DxvkComputePipelineBit::PipelineDirty,
|
||||
DxvkComputePipelineBit::DirtyResources);
|
||||
} else {
|
||||
m_state.g.flags.set(
|
||||
DxvkGraphicsPipelineBit::PipelineDirty,
|
||||
DxvkGraphicsPipelineBit::DirtyResources);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::flushComputeState() {
|
||||
VkCommandBuffer cmd = m_commandList->handle();
|
||||
|
||||
if (m_state.c.flags.test(DxvkComputePipelineBit::PipelineDirty)
|
||||
&& m_state.c.pipeline != nullptr) {
|
||||
m_vkd->vkCmdBindPipeline(cmd,
|
||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||
m_state.c.pipeline->handle());
|
||||
}
|
||||
|
||||
m_state.c.flags.clr(
|
||||
DxvkComputePipelineBit::PipelineDirty,
|
||||
DxvkComputePipelineBit::DirtyResources);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::flushGraphicsState() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::prepareDraw() {
|
||||
this->flushGraphicsState();
|
||||
|
||||
if (!m_state.fb.flags.test(DxvkFbStateFlags::InsideRenderPass))
|
||||
if (!m_state.g.flags.test(DxvkGraphicsPipelineBit::RenderPassBound))
|
||||
this->beginRenderPass();
|
||||
}
|
||||
|
||||
@ -122,22 +172,20 @@ namespace dxvk {
|
||||
void DxvkContext::beginRenderPass() {
|
||||
TRACE(this);
|
||||
|
||||
const DxvkFramebufferSize fbsize
|
||||
= m_state.fb.framebuffer->size();
|
||||
DxvkFramebufferSize fbsize
|
||||
= m_state.g.fb->size();
|
||||
|
||||
VkRenderPassBeginInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
info.pNext = nullptr;
|
||||
info.renderPass = m_state.fb.framebuffer->renderPass();
|
||||
info.framebuffer = m_state.fb.framebuffer->handle();
|
||||
info.renderPass = m_state.g.fb->renderPass();
|
||||
info.framebuffer = m_state.g.fb->handle();
|
||||
info.renderArea = VkRect2D { { 0, 0 }, { fbsize.width, fbsize.height } };
|
||||
info.clearValueCount = 0;
|
||||
info.pClearValues = nullptr;
|
||||
|
||||
m_vkd->vkCmdBeginRenderPass(
|
||||
m_commandList->handle(),
|
||||
&info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
m_state.fb.flags.set(DxvkFbStateFlags::InsideRenderPass);
|
||||
m_vkd->vkCmdBeginRenderPass(m_commandList->handle(), &info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
m_state.g.flags.set(DxvkGraphicsPipelineBit::RenderPassBound);
|
||||
}
|
||||
|
||||
|
||||
@ -145,7 +193,33 @@ namespace dxvk {
|
||||
TRACE(this);
|
||||
|
||||
m_vkd->vkCmdEndRenderPass(m_commandList->handle());
|
||||
m_state.fb.flags.clr(DxvkFbStateFlags::InsideRenderPass);
|
||||
m_state.g.flags.clr(DxvkGraphicsPipelineBit::RenderPassBound);
|
||||
}
|
||||
|
||||
|
||||
DxvkShaderState* DxvkContext::getShaderState(VkShaderStageFlagBits stage) {
|
||||
switch (stage) {
|
||||
case VK_SHADER_STAGE_VERTEX_BIT:
|
||||
return &m_state.g.vs;
|
||||
|
||||
case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
|
||||
return &m_state.g.tcs;
|
||||
|
||||
case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
|
||||
return &m_state.g.tes;
|
||||
|
||||
case VK_SHADER_STAGE_GEOMETRY_BIT:
|
||||
return &m_state.g.gs;
|
||||
|
||||
case VK_SHADER_STAGE_FRAGMENT_BIT:
|
||||
return &m_state.g.fs;
|
||||
|
||||
case VK_SHADER_STAGE_COMPUTE_BIT:
|
||||
return &m_state.c.cs;
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#define DXVK_ERROR_CHECKING 1
|
||||
|
||||
#include "dxvk_cmdlist.h"
|
||||
#include "dxvk_context_state.h"
|
||||
|
||||
@ -61,6 +59,18 @@ namespace dxvk {
|
||||
const VkClearAttachment& attachment,
|
||||
const VkClearRect& clearArea);
|
||||
|
||||
/**
|
||||
* \brief Dispatches compute operations
|
||||
*
|
||||
* \param [in] wgCountX Number of X work groups
|
||||
* \param [in] wgCountY Number of Y work groups
|
||||
* \param [in] wgCountZ Number of Z work groups
|
||||
*/
|
||||
void dispatch(
|
||||
uint32_t wgCountX,
|
||||
uint32_t wgCountY,
|
||||
uint32_t wgCountZ);
|
||||
|
||||
/**
|
||||
* \brief Draws primitive without using an index buffer
|
||||
*
|
||||
@ -118,20 +128,15 @@ namespace dxvk {
|
||||
Rc<DxvkCommandList> m_commandList;
|
||||
DxvkContextState m_state;
|
||||
|
||||
/**
|
||||
* \brief Forces a graphics pipeline state flush
|
||||
*
|
||||
* Applies current shader bindings, resource bindings
|
||||
* etc. to the command buffer so that draw calls can
|
||||
* be executed. Called whenever the need arises.
|
||||
*/
|
||||
void flushComputeState();
|
||||
void flushGraphicsState();
|
||||
|
||||
void prepareDraw();
|
||||
|
||||
void beginRenderPass();
|
||||
void endRenderPass();
|
||||
|
||||
DxvkShaderState* getShaderState(
|
||||
VkShaderStageFlagBits stage);
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -1,21 +1,113 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxvk_compute.h"
|
||||
#include "dxvk_framebuffer.h"
|
||||
#include "dxvk_shader.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
enum class DxvkFbStateFlags : uint32_t {
|
||||
InsideRenderPass = 0,
|
||||
/**
|
||||
* \brief Limits of the DXVK API
|
||||
*
|
||||
* Stores the number of binding slots
|
||||
* available for all resource types.
|
||||
*/
|
||||
enum DxvkLimits : size_t {
|
||||
MaxNumRenderTargets = 8,
|
||||
MaxNumUniformBuffers = 16,
|
||||
MaxNumSampledImages = 16,
|
||||
MaxNumStorageBuffers = 128,
|
||||
MaxNumStorageImages = 128,
|
||||
MaxNumVertexBuffers = 32,
|
||||
MaxNumOutputStreams = 4,
|
||||
};
|
||||
|
||||
struct DxvkFramebufferState {
|
||||
Rc<DxvkFramebuffer> framebuffer;
|
||||
Flags<DxvkFbStateFlags> flags;
|
||||
|
||||
/**
|
||||
* \brief Graphics pipeline state flags
|
||||
*
|
||||
* Stores some information on which state of the
|
||||
* graphics pipeline has changed and/or needs to
|
||||
* be updated.
|
||||
*/
|
||||
enum class DxvkGraphicsPipelineBit : uint64_t {
|
||||
RenderPassBound = 0, ///< If set, a render pass instance is currently active
|
||||
PipelineDirty = 1, ///< If set, the shader pipeline binding is out of date
|
||||
PipelineStateDirty = 2, ///< If set, another pipeline variant needs to be bound
|
||||
DirtyResources = 3, ///< If set, the descriptor set must be updated
|
||||
DirtyVertexBuffers = 4, ///< If set, the vertex buffer bindings need to be updated
|
||||
DirtyIndexBuffer = 5, ///< If set, the index buffer binding needs to be updated
|
||||
};
|
||||
|
||||
using DxvkGraphicsPipelineFlags = Flags<DxvkGraphicsPipelineBit>;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Compute pipeline state flags
|
||||
*
|
||||
* Stores information on whether the compute shader
|
||||
* or any of its resource bindings have been updated.
|
||||
*/
|
||||
enum class DxvkComputePipelineBit : uint64_t {
|
||||
PipelineDirty = 0, ///< If set, the shader pipeline binding is out of date
|
||||
DirtyResources = 1, ///< If set, the descriptor set must be updated
|
||||
};
|
||||
|
||||
using DxvkComputePipelineFlags = Flags<DxvkComputePipelineBit>;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Shader state
|
||||
*
|
||||
* Stores the active shader and resources for a single
|
||||
* shader stage. This includes sampled textures, uniform
|
||||
* buffers, storage buffers and storage images.
|
||||
*/
|
||||
struct DxvkShaderState {
|
||||
Rc<DxvkShader> shader;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Graphics pipeline state
|
||||
*
|
||||
* Stores everything related to graphics
|
||||
* operations, including bound resources.
|
||||
*/
|
||||
struct DxvkGraphicsPipelineState {
|
||||
DxvkShaderState vs;
|
||||
DxvkShaderState tcs;
|
||||
DxvkShaderState tes;
|
||||
DxvkShaderState gs;
|
||||
DxvkShaderState fs;
|
||||
Rc<DxvkFramebuffer> fb;
|
||||
DxvkGraphicsPipelineFlags flags;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Compute pipeline state
|
||||
*
|
||||
* Stores the active compute pipeline and
|
||||
* resources bound to the compute shader.
|
||||
*/
|
||||
struct DxvkComputePipelineState {
|
||||
DxvkShaderState cs;
|
||||
Rc<DxvkComputePipeline> pipeline;
|
||||
DxvkComputePipelineFlags flags;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief DXVK context state
|
||||
*
|
||||
* Stores all graphics pipeline state known
|
||||
* to DXVK. As in Vulkan, graphics and compute
|
||||
* pipeline states are strictly separated.
|
||||
*/
|
||||
struct DxvkContextState {
|
||||
DxvkFramebufferState fb; ///< Framebuffer and render pass
|
||||
DxvkGraphicsPipelineState g;
|
||||
DxvkComputePipelineState c;
|
||||
};
|
||||
|
||||
}
|
@ -8,13 +8,13 @@ namespace dxvk {
|
||||
|
||||
void DxvkLifetimeTracker::trackResource(const Rc<DxvkResource>& rc) {
|
||||
if (m_resources.insert(rc).second)
|
||||
rc->incUseCount();
|
||||
rc->acquire();
|
||||
}
|
||||
|
||||
|
||||
void DxvkLifetimeTracker::reset() {
|
||||
for (auto i = m_resources.cbegin(); i != m_resources.cend(); i++)
|
||||
(*i)->decUseCount();
|
||||
(*i)->release();
|
||||
m_resources.clear();
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,8 @@ namespace dxvk {
|
||||
return m_useCount != 0;
|
||||
}
|
||||
|
||||
void incUseCount() { m_useCount += 1; }
|
||||
void decUseCount() { m_useCount -= 1; }
|
||||
void acquire() { m_useCount += 1; }
|
||||
void release() { m_useCount -= 1; }
|
||||
|
||||
private:
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
dxvk_src = files([
|
||||
'dxvk_adapter.cpp',
|
||||
'dxvk_cmdlist.cpp',
|
||||
'dxvk_compute.cpp',
|
||||
'dxvk_context.cpp',
|
||||
'dxvk_device.cpp',
|
||||
'dxvk_framebuffer.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user