mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-27 04:54:15 +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);
|
TRACE(this, cmdList);
|
||||||
m_commandList = cmdList;
|
m_commandList = cmdList;
|
||||||
m_commandList->beginRecording();
|
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() {
|
bool DxvkContext::endRecording() {
|
||||||
TRACE(this);
|
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();
|
this->endRenderPass();
|
||||||
|
|
||||||
// Finalize the command list
|
// Finalize the command list
|
||||||
@ -38,8 +55,7 @@ namespace dxvk {
|
|||||||
void DxvkContext::clearRenderTarget(
|
void DxvkContext::clearRenderTarget(
|
||||||
const VkClearAttachment& attachment,
|
const VkClearAttachment& attachment,
|
||||||
const VkClearRect& clearArea) {
|
const VkClearRect& clearArea) {
|
||||||
if (!m_state.fb.flags.test(DxvkFbStateFlags::InsideRenderPass))
|
this->flushGraphicsState();
|
||||||
this->beginRenderPass();
|
|
||||||
|
|
||||||
m_vkd->vkCmdClearAttachments(
|
m_vkd->vkCmdClearAttachments(
|
||||||
m_commandList->handle(),
|
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(
|
void DxvkContext::draw(
|
||||||
uint32_t vertexCount,
|
uint32_t vertexCount,
|
||||||
uint32_t instanceCount,
|
uint32_t instanceCount,
|
||||||
uint32_t firstVertex,
|
uint32_t firstVertex,
|
||||||
uint32_t firstInstance) {
|
uint32_t firstInstance) {
|
||||||
this->prepareDraw();
|
this->flushGraphicsState();
|
||||||
|
|
||||||
m_vkd->vkCmdDraw(
|
m_vkd->vkCmdDraw(
|
||||||
m_commandList->handle(),
|
m_commandList->handle(),
|
||||||
vertexCount,
|
vertexCount,
|
||||||
@ -69,7 +98,8 @@ namespace dxvk {
|
|||||||
uint32_t firstIndex,
|
uint32_t firstIndex,
|
||||||
uint32_t vertexOffset,
|
uint32_t vertexOffset,
|
||||||
uint32_t firstInstance) {
|
uint32_t firstInstance) {
|
||||||
this->prepareDraw();
|
this->flushGraphicsState();
|
||||||
|
|
||||||
m_vkd->vkCmdDrawIndexed(
|
m_vkd->vkCmdDrawIndexed(
|
||||||
m_commandList->handle(),
|
m_commandList->handle(),
|
||||||
indexCount,
|
indexCount,
|
||||||
@ -84,37 +114,57 @@ namespace dxvk {
|
|||||||
const Rc<DxvkFramebuffer>& fb) {
|
const Rc<DxvkFramebuffer>& fb) {
|
||||||
TRACE(this, fb);
|
TRACE(this, fb);
|
||||||
|
|
||||||
// When changing the framebuffer binding, we end the
|
if (m_state.g.fb != fb) {
|
||||||
// current render pass, but beginning the new render
|
m_state.g.fb = fb;
|
||||||
// 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();
|
|
||||||
|
|
||||||
m_state.fb.framebuffer = fb;
|
if (m_state.g.flags.test(
|
||||||
m_commandList->trackResource(fb);
|
DxvkGraphicsPipelineBit::RenderPassBound))
|
||||||
|
this->endRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::setShader(
|
void DxvkContext::setShader(
|
||||||
VkShaderStageFlagBits stage,
|
VkShaderStageFlagBits stage,
|
||||||
const Rc<DxvkShader>& shader) {
|
const Rc<DxvkShader>& shader) {
|
||||||
TRACE(this, stage, 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::flushGraphicsState() {
|
||||||
|
if (!m_state.g.flags.test(DxvkGraphicsPipelineBit::RenderPassBound))
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::prepareDraw() {
|
|
||||||
this->flushGraphicsState();
|
|
||||||
|
|
||||||
if (!m_state.fb.flags.test(DxvkFbStateFlags::InsideRenderPass))
|
|
||||||
this->beginRenderPass();
|
this->beginRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,22 +172,20 @@ namespace dxvk {
|
|||||||
void DxvkContext::beginRenderPass() {
|
void DxvkContext::beginRenderPass() {
|
||||||
TRACE(this);
|
TRACE(this);
|
||||||
|
|
||||||
const DxvkFramebufferSize fbsize
|
DxvkFramebufferSize fbsize
|
||||||
= m_state.fb.framebuffer->size();
|
= m_state.g.fb->size();
|
||||||
|
|
||||||
VkRenderPassBeginInfo info;
|
VkRenderPassBeginInfo info;
|
||||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||||
info.pNext = nullptr;
|
info.pNext = nullptr;
|
||||||
info.renderPass = m_state.fb.framebuffer->renderPass();
|
info.renderPass = m_state.g.fb->renderPass();
|
||||||
info.framebuffer = m_state.fb.framebuffer->handle();
|
info.framebuffer = m_state.g.fb->handle();
|
||||||
info.renderArea = VkRect2D { { 0, 0 }, { fbsize.width, fbsize.height } };
|
info.renderArea = VkRect2D { { 0, 0 }, { fbsize.width, fbsize.height } };
|
||||||
info.clearValueCount = 0;
|
info.clearValueCount = 0;
|
||||||
info.pClearValues = nullptr;
|
info.pClearValues = nullptr;
|
||||||
|
|
||||||
m_vkd->vkCmdBeginRenderPass(
|
m_vkd->vkCmdBeginRenderPass(m_commandList->handle(), &info, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
m_commandList->handle(),
|
m_state.g.flags.set(DxvkGraphicsPipelineBit::RenderPassBound);
|
||||||
&info, VK_SUBPASS_CONTENTS_INLINE);
|
|
||||||
m_state.fb.flags.set(DxvkFbStateFlags::InsideRenderPass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -145,7 +193,33 @@ namespace dxvk {
|
|||||||
TRACE(this);
|
TRACE(this);
|
||||||
|
|
||||||
m_vkd->vkCmdEndRenderPass(m_commandList->handle());
|
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
|
#pragma once
|
||||||
|
|
||||||
#define DXVK_ERROR_CHECKING 1
|
|
||||||
|
|
||||||
#include "dxvk_cmdlist.h"
|
#include "dxvk_cmdlist.h"
|
||||||
#include "dxvk_context_state.h"
|
#include "dxvk_context_state.h"
|
||||||
|
|
||||||
@ -61,6 +59,18 @@ namespace dxvk {
|
|||||||
const VkClearAttachment& attachment,
|
const VkClearAttachment& attachment,
|
||||||
const VkClearRect& clearArea);
|
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
|
* \brief Draws primitive without using an index buffer
|
||||||
*
|
*
|
||||||
@ -118,20 +128,15 @@ namespace dxvk {
|
|||||||
Rc<DxvkCommandList> m_commandList;
|
Rc<DxvkCommandList> m_commandList;
|
||||||
DxvkContextState m_state;
|
DxvkContextState m_state;
|
||||||
|
|
||||||
/**
|
void flushComputeState();
|
||||||
* \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 flushGraphicsState();
|
void flushGraphicsState();
|
||||||
|
|
||||||
void prepareDraw();
|
|
||||||
|
|
||||||
void beginRenderPass();
|
void beginRenderPass();
|
||||||
void endRenderPass();
|
void endRenderPass();
|
||||||
|
|
||||||
|
DxvkShaderState* getShaderState(
|
||||||
|
VkShaderStageFlagBits stage);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -1,21 +1,113 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "dxvk_compute.h"
|
||||||
#include "dxvk_framebuffer.h"
|
#include "dxvk_framebuffer.h"
|
||||||
#include "dxvk_shader.h"
|
#include "dxvk_shader.h"
|
||||||
|
|
||||||
namespace dxvk {
|
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 {
|
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) {
|
void DxvkLifetimeTracker::trackResource(const Rc<DxvkResource>& rc) {
|
||||||
if (m_resources.insert(rc).second)
|
if (m_resources.insert(rc).second)
|
||||||
rc->incUseCount();
|
rc->acquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkLifetimeTracker::reset() {
|
void DxvkLifetimeTracker::reset() {
|
||||||
for (auto i = m_resources.cbegin(); i != m_resources.cend(); i++)
|
for (auto i = m_resources.cbegin(); i != m_resources.cend(); i++)
|
||||||
(*i)->decUseCount();
|
(*i)->release();
|
||||||
m_resources.clear();
|
m_resources.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@ namespace dxvk {
|
|||||||
return m_useCount != 0;
|
return m_useCount != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void incUseCount() { m_useCount += 1; }
|
void acquire() { m_useCount += 1; }
|
||||||
void decUseCount() { m_useCount -= 1; }
|
void release() { m_useCount -= 1; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
dxvk_src = files([
|
dxvk_src = files([
|
||||||
'dxvk_adapter.cpp',
|
'dxvk_adapter.cpp',
|
||||||
'dxvk_cmdlist.cpp',
|
'dxvk_cmdlist.cpp',
|
||||||
|
'dxvk_compute.cpp',
|
||||||
'dxvk_context.cpp',
|
'dxvk_context.cpp',
|
||||||
'dxvk_device.cpp',
|
'dxvk_device.cpp',
|
||||||
'dxvk_framebuffer.cpp',
|
'dxvk_framebuffer.cpp',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user