mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-11-29 01:24:11 +01:00
[dxvk] Some more work on shader resources and resource bindings
This commit is contained in:
parent
44d9bd9000
commit
e433c01ad4
70
src/dxvk/dxvk_barrier.cpp
Normal file
70
src/dxvk/dxvk_barrier.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
#include "dxvk_barrier.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkBarrierSet:: DxvkBarrierSet() { }
|
||||
DxvkBarrierSet::~DxvkBarrierSet() { }
|
||||
|
||||
bool DxvkBarrierSet::hasBarriers() const {
|
||||
return (m_srcFlags | m_dstFlags) != 0;
|
||||
}
|
||||
|
||||
|
||||
void DxvkBarrierSet::addMemoryBarrier(
|
||||
VkPipelineStageFlags srcFlags,
|
||||
VkPipelineStageFlags dstFlags,
|
||||
const VkMemoryBarrier& barrier) {
|
||||
m_srcFlags |= srcFlags;
|
||||
m_dstFlags |= dstFlags;
|
||||
m_memory.push_back(barrier);
|
||||
}
|
||||
|
||||
|
||||
void DxvkBarrierSet::addBufferBarrier(
|
||||
VkPipelineStageFlags srcFlags,
|
||||
VkPipelineStageFlags dstFlags,
|
||||
const VkBufferMemoryBarrier& barrier) {
|
||||
m_srcFlags |= srcFlags;
|
||||
m_dstFlags |= dstFlags;
|
||||
m_buffer.push_back(barrier);
|
||||
}
|
||||
|
||||
|
||||
void DxvkBarrierSet::addImageBarrier(
|
||||
VkPipelineStageFlags srcFlags,
|
||||
VkPipelineStageFlags dstFlags,
|
||||
const VkImageMemoryBarrier& barrier) {
|
||||
m_srcFlags |= srcFlags;
|
||||
m_dstFlags |= dstFlags;
|
||||
m_image.push_back(barrier);
|
||||
}
|
||||
|
||||
|
||||
void DxvkBarrierSet::recordCommands(
|
||||
DxvkRecorder& recorder) {
|
||||
VkPipelineStageFlags srcFlags = m_srcFlags;
|
||||
VkPipelineStageFlags dstFlags = m_dstFlags;
|
||||
|
||||
if (srcFlags == 0) srcFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
if (dstFlags == 0) dstFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||
|
||||
recorder.cmdPipelineBarrier(
|
||||
srcFlags, dstFlags, 0,
|
||||
m_memory.size(), m_memory.data(),
|
||||
m_buffer.size(), m_buffer.data(),
|
||||
m_image.size(), m_image.data());
|
||||
|
||||
this->reset();
|
||||
}
|
||||
|
||||
|
||||
void DxvkBarrierSet::reset() {
|
||||
m_srcFlags = 0;
|
||||
m_dstFlags = 0;
|
||||
|
||||
m_memory.resize(0);
|
||||
m_buffer.resize(0);
|
||||
m_image .resize(0);
|
||||
}
|
||||
|
||||
}
|
54
src/dxvk/dxvk_barrier.h
Normal file
54
src/dxvk/dxvk_barrier.h
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxvk_recorder.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Barrier set
|
||||
*
|
||||
* Accumulates memory barriers and provides a
|
||||
* method to record all those barriers into a
|
||||
* command buffer at once.
|
||||
*/
|
||||
class DxvkBarrierSet {
|
||||
|
||||
public:
|
||||
|
||||
DxvkBarrierSet();
|
||||
~DxvkBarrierSet();
|
||||
|
||||
bool hasBarriers() const;
|
||||
|
||||
void addMemoryBarrier(
|
||||
VkPipelineStageFlags srcFlags,
|
||||
VkPipelineStageFlags dstFlags,
|
||||
const VkMemoryBarrier& barrier);
|
||||
|
||||
void addBufferBarrier(
|
||||
VkPipelineStageFlags srcFlags,
|
||||
VkPipelineStageFlags dstFlags,
|
||||
const VkBufferMemoryBarrier& barrier);
|
||||
|
||||
void addImageBarrier(
|
||||
VkPipelineStageFlags srcFlags,
|
||||
VkPipelineStageFlags dstFlags,
|
||||
const VkImageMemoryBarrier& barrier);
|
||||
|
||||
void recordCommands(
|
||||
DxvkRecorder& recorder);
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
|
||||
VkPipelineStageFlags m_srcFlags = 0;
|
||||
VkPipelineStageFlags m_dstFlags = 0;
|
||||
|
||||
std::vector<VkMemoryBarrier> m_memory;
|
||||
std::vector<VkBufferMemoryBarrier> m_buffer;
|
||||
std::vector<VkImageMemoryBarrier> m_image;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -19,6 +19,13 @@ namespace dxvk {
|
||||
/// Buffer usage flags
|
||||
VkBufferUsageFlags usage;
|
||||
|
||||
/// Pipeline stages that can access
|
||||
/// the contents of the buffer.
|
||||
VkPipelineStageFlags stages;
|
||||
|
||||
/// Allowed access patterns
|
||||
VkAccessFlags access;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -77,4 +84,57 @@ namespace dxvk {
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Buffer binding
|
||||
*
|
||||
* Stores the buffer and the sub-range of the buffer
|
||||
* to bind. Bindings are considered equal if all three
|
||||
* parameters are the same.
|
||||
*/
|
||||
class DxvkBufferBinding {
|
||||
|
||||
public:
|
||||
|
||||
DxvkBufferBinding() { }
|
||||
DxvkBufferBinding(
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize rangeOffset,
|
||||
VkDeviceSize rangeLength)
|
||||
: m_buffer(buffer),
|
||||
m_offset(rangeOffset),
|
||||
m_length(rangeLength) { }
|
||||
|
||||
Rc<DxvkResource> resource() const {
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
VkDescriptorBufferInfo descriptorInfo() const {
|
||||
VkDescriptorBufferInfo info;
|
||||
info.buffer = m_buffer->handle();
|
||||
info.offset = m_offset;
|
||||
info.range = m_length;
|
||||
return info;
|
||||
}
|
||||
|
||||
bool operator == (const DxvkBufferBinding& other) const {
|
||||
return this->m_buffer == other.m_buffer
|
||||
&& this->m_offset == other.m_offset
|
||||
&& this->m_length == other.m_length;
|
||||
}
|
||||
|
||||
bool operator != (const DxvkBufferBinding& other) const {
|
||||
return this->m_buffer != other.m_buffer
|
||||
|| this->m_offset != other.m_offset
|
||||
|| this->m_length != other.m_length;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Rc<DxvkBuffer> m_buffer = nullptr;
|
||||
VkDeviceSize m_offset = 0;
|
||||
VkDeviceSize m_length = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -138,4 +138,22 @@ namespace dxvk {
|
||||
m_vkd->vkCmdEndRenderPass(m_buffer);
|
||||
}
|
||||
|
||||
|
||||
void DxvkCommandList::cmdPipelineBarrier(
|
||||
VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask,
|
||||
VkDependencyFlags dependencyFlags,
|
||||
uint32_t memoryBarrierCount,
|
||||
const VkMemoryBarrier* pMemoryBarriers,
|
||||
uint32_t bufferMemoryBarrierCount,
|
||||
const VkBufferMemoryBarrier* pBufferMemoryBarriers,
|
||||
uint32_t imageMemoryBarrierCount,
|
||||
const VkImageMemoryBarrier* pImageMemoryBarriers) {
|
||||
m_vkd->vkCmdPipelineBarrier(m_buffer,
|
||||
dstStageMask, srcStageMask, dependencyFlags,
|
||||
memoryBarrierCount, pMemoryBarriers,
|
||||
bufferMemoryBarrierCount, pBufferMemoryBarriers,
|
||||
imageMemoryBarrierCount, pImageMemoryBarriers);
|
||||
}
|
||||
|
||||
}
|
@ -104,6 +104,17 @@ namespace dxvk {
|
||||
|
||||
void cmdEndRenderPass() final;
|
||||
|
||||
void cmdPipelineBarrier(
|
||||
VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask,
|
||||
VkDependencyFlags dependencyFlags,
|
||||
uint32_t memoryBarrierCount,
|
||||
const VkMemoryBarrier* pMemoryBarriers,
|
||||
uint32_t bufferMemoryBarrierCount,
|
||||
const VkBufferMemoryBarrier* pBufferMemoryBarriers,
|
||||
uint32_t imageMemoryBarrierCount,
|
||||
const VkImageMemoryBarrier* pImageMemoryBarriers) final;
|
||||
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
|
@ -6,6 +6,7 @@ namespace dxvk {
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkShader>& shader)
|
||||
: m_vkd(vkd) {
|
||||
TRACE(this, shader);
|
||||
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings;
|
||||
|
||||
@ -80,6 +81,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
DxvkComputePipeline::~DxvkComputePipeline() {
|
||||
TRACE(this);
|
||||
this->destroyObjects();
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,11 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkContext::DxvkContext(const Rc<DxvkDevice>& device)
|
||||
: m_device(device) {
|
||||
DxvkContext::DxvkContext(
|
||||
const Rc<DxvkDevice>& device,
|
||||
const Rc<DxvkPipelineManager>& pipeMgr)
|
||||
: m_device (device),
|
||||
m_pipeMgr (pipeMgr) {
|
||||
TRACE(this, device);
|
||||
}
|
||||
|
||||
@ -53,6 +56,57 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindFramebuffer(
|
||||
const Rc<DxvkFramebuffer>& fb) {
|
||||
TRACE(this, fb);
|
||||
|
||||
if (m_state.g.fb != fb) {
|
||||
m_state.g.fb = fb;
|
||||
|
||||
if (m_state.g.flags.test(
|
||||
DxvkGraphicsPipelineBit::RenderPassBound))
|
||||
this->endRenderPass();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindShader(
|
||||
VkShaderStageFlagBits stage,
|
||||
const Rc<DxvkShader>& shader) {
|
||||
TRACE(this, stage, shader);
|
||||
|
||||
DxvkShaderState* state = this->getShaderState(stage);
|
||||
|
||||
if (state->shader != shader) {
|
||||
state->shader = shader;
|
||||
this->setPipelineDirty(stage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindStorageBuffer(
|
||||
VkShaderStageFlagBits stage,
|
||||
uint32_t slot,
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize offset,
|
||||
VkDeviceSize length) {
|
||||
TRACE(this, stage, slot);
|
||||
|
||||
DxvkBufferBinding binding(buffer, offset, length);
|
||||
DxvkShaderState* state = this->getShaderState(stage);
|
||||
|
||||
// TODO investigate whether it is worth checking whether
|
||||
// the shader actually uses the resource. However, if the
|
||||
// application is not completely retarded, always setting
|
||||
// the 'resources dirty' flag should be the best option.
|
||||
if (state->boundStorageBuffers.at(slot) != binding) {
|
||||
state->boundStorageBuffers.at(slot) = binding;
|
||||
this->setResourcesDirty(stage);
|
||||
m_cmd->trackResource(binding.resource());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::clearRenderTarget(
|
||||
const VkClearAttachment& attachment,
|
||||
const VkClearRect& clearArea) {
|
||||
@ -67,6 +121,8 @@ namespace dxvk {
|
||||
uint32_t wgCountX,
|
||||
uint32_t wgCountY,
|
||||
uint32_t wgCountZ) {
|
||||
TRACE(this, wgCountX, wgCountY, wgCountZ);
|
||||
this->endRenderPass();
|
||||
this->flushComputeState();
|
||||
|
||||
m_cmd->cmdDispatch(
|
||||
@ -79,6 +135,8 @@ namespace dxvk {
|
||||
uint32_t instanceCount,
|
||||
uint32_t firstVertex,
|
||||
uint32_t firstInstance) {
|
||||
TRACE(this, vertexCount, instanceCount,
|
||||
firstVertex, firstInstance);
|
||||
this->flushGraphicsState();
|
||||
|
||||
m_cmd->cmdDraw(
|
||||
@ -93,6 +151,8 @@ namespace dxvk {
|
||||
uint32_t firstIndex,
|
||||
uint32_t vertexOffset,
|
||||
uint32_t firstInstance) {
|
||||
TRACE(this, indexCount, instanceCount,
|
||||
firstIndex, vertexOffset, firstInstance);
|
||||
this->flushGraphicsState();
|
||||
|
||||
m_cmd->cmdDrawIndexed(
|
||||
@ -102,49 +162,15 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::setFramebuffer(
|
||||
const Rc<DxvkFramebuffer>& fb) {
|
||||
TRACE(this, fb);
|
||||
|
||||
if (m_state.g.fb != fb) {
|
||||
m_state.g.fb = 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() {
|
||||
if (m_state.c.flags.test(DxvkComputePipelineBit::PipelineDirty)
|
||||
&& m_state.c.pipeline != nullptr) {
|
||||
m_cmd->cmdBindPipeline(
|
||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||
m_state.c.pipeline->getPipelineHandle());
|
||||
if (m_state.c.flags.test(DxvkComputePipelineBit::PipelineDirty)) {
|
||||
m_state.c.pipeline = m_pipeMgr->getComputePipeline(m_state.c.cs.shader);
|
||||
|
||||
if (m_state.c.pipeline != nullptr) {
|
||||
m_cmd->cmdBindPipeline(
|
||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||
m_state.c.pipeline->getPipelineHandle());
|
||||
}
|
||||
}
|
||||
|
||||
m_state.c.flags.clr(
|
||||
@ -187,6 +213,27 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::setPipelineDirty(VkShaderStageFlagBits stage) {
|
||||
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::setResourcesDirty(VkShaderStageFlagBits stage) {
|
||||
if (stage == VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
m_state.c.flags.set(DxvkComputePipelineBit::DirtyResources);
|
||||
else
|
||||
m_state.g.flags.set(DxvkGraphicsPipelineBit::DirtyResources);
|
||||
}
|
||||
|
||||
|
||||
DxvkShaderState* DxvkContext::getShaderState(VkShaderStageFlagBits stage) {
|
||||
switch (stage) {
|
||||
case VK_SHADER_STAGE_VERTEX_BIT:
|
||||
|
@ -1,8 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxvk_barrier.h"
|
||||
#include "dxvk_cmdlist.h"
|
||||
#include "dxvk_context_state.h"
|
||||
#include "dxvk_deferred.h"
|
||||
#include "dxvk_pipemgr.h"
|
||||
#include "dxvk_util.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
@ -18,7 +21,8 @@ namespace dxvk {
|
||||
public:
|
||||
|
||||
DxvkContext(
|
||||
const Rc<DxvkDevice>& device);
|
||||
const Rc<DxvkDevice>& device,
|
||||
const Rc<DxvkPipelineManager>& pipeMgr);
|
||||
~DxvkContext();
|
||||
|
||||
/**
|
||||
@ -51,6 +55,41 @@ namespace dxvk {
|
||||
*/
|
||||
bool endRecording();
|
||||
|
||||
/**
|
||||
* \brief Sets framebuffer
|
||||
* \param [in] fb Framebuffer
|
||||
*/
|
||||
void bindFramebuffer(
|
||||
const Rc<DxvkFramebuffer>& fb);
|
||||
|
||||
/**
|
||||
* \brief Sets shader for a given shader stage
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
void bindShader(
|
||||
VkShaderStageFlagBits stage,
|
||||
const Rc<DxvkShader>& shader);
|
||||
|
||||
/**
|
||||
* \brief Binds a storage buffer
|
||||
*
|
||||
* \param [in] stage Shader stage for this binding
|
||||
* \param [in] slot Binding slot index
|
||||
* \param [in] buffer Buffer binding info
|
||||
*/
|
||||
void bindStorageBuffer(
|
||||
VkShaderStageFlagBits stage,
|
||||
uint32_t slot,
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize offset,
|
||||
VkDeviceSize length);
|
||||
|
||||
/**
|
||||
* \brief Clears an active render target
|
||||
*
|
||||
@ -103,30 +142,10 @@ namespace dxvk {
|
||||
uint32_t vertexOffset,
|
||||
uint32_t firstInstance);
|
||||
|
||||
/**
|
||||
* \brief Sets framebuffer
|
||||
* \param [in] fb Framebuffer
|
||||
*/
|
||||
void setFramebuffer(
|
||||
const Rc<DxvkFramebuffer>& fb);
|
||||
|
||||
/**
|
||||
* \brief Sets shader for a given shader stage
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
void setShader(
|
||||
VkShaderStageFlagBits stage,
|
||||
const Rc<DxvkShader>& shader);
|
||||
|
||||
private:
|
||||
|
||||
const Rc<DxvkDevice> m_device;
|
||||
const Rc<DxvkDevice> m_device;
|
||||
const Rc<DxvkPipelineManager> m_pipeMgr;
|
||||
|
||||
Rc<DxvkRecorder> m_cmd;
|
||||
DxvkContextState m_state;
|
||||
@ -137,9 +156,19 @@ namespace dxvk {
|
||||
void beginRenderPass();
|
||||
void endRenderPass();
|
||||
|
||||
void setPipelineDirty(VkShaderStageFlagBits stage);
|
||||
void setResourcesDirty(VkShaderStageFlagBits stage);
|
||||
|
||||
void shaderResourceBarriers(
|
||||
DxvkBarrierSet& barriers,
|
||||
VkShaderStageFlagBits stage);
|
||||
|
||||
DxvkShaderState* getShaderState(
|
||||
VkShaderStageFlagBits stage);
|
||||
|
||||
VkPipelineStageFlags pipelineStage(
|
||||
VkShaderStageFlags shaderStage) const;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxvk_buffer.h"
|
||||
#include "dxvk_compute.h"
|
||||
#include "dxvk_framebuffer.h"
|
||||
#include "dxvk_image.h"
|
||||
#include "dxvk_limits.h"
|
||||
#include "dxvk_shader.h"
|
||||
|
||||
@ -48,7 +50,10 @@ namespace dxvk {
|
||||
* buffers, storage buffers and storage images.
|
||||
*/
|
||||
struct DxvkShaderState {
|
||||
Rc<DxvkShader> shader;
|
||||
Rc<DxvkShader> shader;
|
||||
|
||||
std::array<DxvkBufferBinding, MaxNumStorageBuffers> boundStorageBuffers;
|
||||
std::array<DxvkBufferBinding, MaxNumUniformBuffers> boundUniformBuffers;
|
||||
};
|
||||
|
||||
|
||||
|
@ -6,10 +6,11 @@ namespace dxvk {
|
||||
DxvkDevice::DxvkDevice(
|
||||
const Rc<DxvkAdapter>& adapter,
|
||||
const Rc<vk::DeviceFn>& vkd)
|
||||
: m_adapter (adapter),
|
||||
m_vkd (vkd),
|
||||
m_memory (adapter, vkd),
|
||||
m_renderPassPool(vkd) {
|
||||
: m_adapter (adapter),
|
||||
m_vkd (vkd),
|
||||
m_memory (new DxvkMemoryAllocator(adapter, vkd)),
|
||||
m_renderPassPool (new DxvkRenderPassPool (vkd)),
|
||||
m_pipelineManager (new DxvkPipelineManager(vkd)) {
|
||||
TRACE(this, adapter);
|
||||
|
||||
m_vkd->vkGetDeviceQueue(m_vkd->device(),
|
||||
@ -23,6 +24,10 @@ namespace dxvk {
|
||||
|
||||
DxvkDevice::~DxvkDevice() {
|
||||
TRACE(this);
|
||||
m_pipelineManager = nullptr;
|
||||
m_renderPassPool = nullptr;
|
||||
m_memory = nullptr;
|
||||
|
||||
m_vkd->vkDeviceWaitIdle(m_vkd->device());
|
||||
m_vkd->vkDestroyDevice(m_vkd->device(), nullptr);
|
||||
}
|
||||
@ -35,14 +40,14 @@ namespace dxvk {
|
||||
|
||||
|
||||
Rc<DxvkContext> DxvkDevice::createContext() {
|
||||
return new DxvkContext(this);
|
||||
return new DxvkContext(this, m_pipelineManager);
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkFramebuffer> DxvkDevice::createFramebuffer(
|
||||
const DxvkRenderTargets& renderTargets) {
|
||||
auto format = renderTargets.renderPassFormat();
|
||||
auto renderPass = m_renderPassPool.getRenderPass(format);
|
||||
auto renderPass = m_renderPassPool->getRenderPass(format);
|
||||
return new DxvkFramebuffer(m_vkd, renderPass, renderTargets);
|
||||
}
|
||||
|
||||
@ -51,7 +56,7 @@ namespace dxvk {
|
||||
const DxvkBufferCreateInfo& createInfo,
|
||||
VkMemoryPropertyFlags memoryType) {
|
||||
return new DxvkBuffer(m_vkd,
|
||||
createInfo, m_memory, memoryType);
|
||||
createInfo, *m_memory, memoryType);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "dxvk_context.h"
|
||||
#include "dxvk_framebuffer.h"
|
||||
#include "dxvk_memory.h"
|
||||
#include "dxvk_pipemgr.h"
|
||||
#include "dxvk_renderpass.h"
|
||||
#include "dxvk_shader.h"
|
||||
#include "dxvk_swapchain.h"
|
||||
@ -179,13 +180,13 @@ namespace dxvk {
|
||||
Rc<DxvkAdapter> m_adapter;
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
|
||||
DxvkMemoryAllocator m_memory;
|
||||
DxvkRenderPassPool m_renderPassPool;
|
||||
Rc<DxvkMemoryAllocator> m_memory;
|
||||
Rc<DxvkRenderPassPool> m_renderPassPool;
|
||||
Rc<DxvkPipelineManager> m_pipelineManager;
|
||||
|
||||
VkQueue m_graphicsQueue;
|
||||
VkQueue m_presentQueue;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -2,17 +2,17 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
size_t DxvkGraphicsPipelineState::hash() const {
|
||||
size_t DxvkGraphicsPipelineStateInfo::hash() const {
|
||||
// TODO implement
|
||||
}
|
||||
|
||||
|
||||
bool DxvkGraphicsPipelineState::operator == (const DxvkGraphicsPipelineState& other) const {
|
||||
bool DxvkGraphicsPipelineStateInfo::operator == (const DxvkGraphicsPipelineStateInfo& other) const {
|
||||
// TODO implement
|
||||
}
|
||||
|
||||
|
||||
bool DxvkGraphicsPipelineState::operator != (const DxvkGraphicsPipelineState& other) const {
|
||||
bool DxvkGraphicsPipelineStateInfo::operator != (const DxvkGraphicsPipelineStateInfo& other) const {
|
||||
return !this->operator == (other);
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
VkPipeline DxvkGraphicsPipeline::getPipelineHandle(
|
||||
const DxvkGraphicsPipelineState& state) {
|
||||
const DxvkGraphicsPipelineStateInfo& state) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
auto pair = m_pipelines.find(state);
|
||||
@ -50,7 +50,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
VkPipeline DxvkGraphicsPipeline::compilePipeline(
|
||||
const DxvkGraphicsPipelineState& state) const {
|
||||
const DxvkGraphicsPipelineStateInfo& state) const {
|
||||
|
||||
}
|
||||
|
||||
|
@ -9,13 +9,13 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
struct DxvkGraphicsPipelineState {
|
||||
struct DxvkGraphicsPipelineStateInfo {
|
||||
VkRenderPass renderPass;
|
||||
|
||||
size_t hash() const;
|
||||
|
||||
bool operator == (const DxvkGraphicsPipelineState& other) const;
|
||||
bool operator != (const DxvkGraphicsPipelineState& other) const;
|
||||
bool operator == (const DxvkGraphicsPipelineStateInfo& other) const;
|
||||
bool operator != (const DxvkGraphicsPipelineStateInfo& other) const;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -43,7 +43,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
VkPipeline getPipelineHandle(
|
||||
const DxvkGraphicsPipelineState& state);
|
||||
const DxvkGraphicsPipelineStateInfo& state);
|
||||
|
||||
private:
|
||||
|
||||
@ -60,11 +60,11 @@ namespace dxvk {
|
||||
std::mutex m_mutex;
|
||||
|
||||
std::unordered_map<
|
||||
DxvkGraphicsPipelineState,
|
||||
DxvkGraphicsPipelineStateInfo,
|
||||
VkPipeline, DxvkHash> m_pipelines;
|
||||
|
||||
VkPipeline compilePipeline(
|
||||
const DxvkGraphicsPipelineState& state) const;
|
||||
const DxvkGraphicsPipelineStateInfo& state) const;
|
||||
|
||||
};
|
||||
|
||||
|
@ -68,7 +68,7 @@ namespace dxvk {
|
||||
* Allocates device memory for Vulkan resources.
|
||||
* Memory objects will be destroyed automatically.
|
||||
*/
|
||||
class DxvkMemoryAllocator {
|
||||
class DxvkMemoryAllocator : public RcObject {
|
||||
friend class DxvkMemory;
|
||||
public:
|
||||
|
||||
|
@ -14,8 +14,9 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkComputePipeline> DxvkPipelineManager::getComputePipeline(
|
||||
const Rc<DxvkShader>& cs) {
|
||||
Rc<DxvkComputePipeline> DxvkPipelineManager::getComputePipeline(const Rc<DxvkShader>& cs) {
|
||||
if (cs == nullptr)
|
||||
return nullptr;
|
||||
|
||||
DxvkPipelineKey<1> key;
|
||||
key.setShader(0, cs);
|
||||
@ -38,6 +39,8 @@ namespace dxvk {
|
||||
const Rc<DxvkShader>& tes,
|
||||
const Rc<DxvkShader>& gs,
|
||||
const Rc<DxvkShader>& fs) {
|
||||
if (vs == nullptr)
|
||||
return nullptr;
|
||||
|
||||
DxvkPipelineKey<5> key;
|
||||
key.setShader(0, vs);
|
||||
|
@ -73,6 +73,7 @@ namespace dxvk {
|
||||
* 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);
|
||||
|
@ -61,6 +61,17 @@ namespace dxvk {
|
||||
|
||||
virtual void cmdEndRenderPass() = 0;
|
||||
|
||||
virtual void cmdPipelineBarrier(
|
||||
VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask,
|
||||
VkDependencyFlags dependencyFlags,
|
||||
uint32_t memoryBarrierCount,
|
||||
const VkMemoryBarrier* pMemoryBarriers,
|
||||
uint32_t bufferMemoryBarrierCount,
|
||||
const VkBufferMemoryBarrier* pBufferMemoryBarriers,
|
||||
uint32_t imageMemoryBarrierCount,
|
||||
const VkImageMemoryBarrier* pImageMemoryBarriers) = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -140,7 +140,7 @@ namespace dxvk {
|
||||
* Thread-safe class that manages the render pass
|
||||
* objects that are used within an application.
|
||||
*/
|
||||
class DxvkRenderPassPool {
|
||||
class DxvkRenderPassPool : public RcObject {
|
||||
|
||||
public:
|
||||
|
||||
|
@ -8,6 +8,19 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Resource access mode
|
||||
*
|
||||
* Defines whether a resource will be
|
||||
* used for reading, writing, or both.
|
||||
*/
|
||||
enum class DxvkResourceModeBit : uint32_t {
|
||||
Read = 0,
|
||||
Write = 1,
|
||||
};
|
||||
|
||||
using DxvkResourceMode = Flags<DxvkResourceModeBit>;
|
||||
|
||||
/**
|
||||
* \brief Shader resource type
|
||||
*
|
||||
@ -27,6 +40,7 @@ namespace dxvk {
|
||||
* \brief Resource slot
|
||||
*/
|
||||
struct DxvkResourceSlot{
|
||||
DxvkResourceMode mode;
|
||||
DxvkResourceType type;
|
||||
uint32_t slot;
|
||||
};
|
||||
|
23
src/dxvk/dxvk_util.cpp
Normal file
23
src/dxvk/dxvk_util.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "dxvk_util.h"
|
||||
|
||||
namespace dxvk::util {
|
||||
|
||||
VkPipelineStageFlags pipelineStages(
|
||||
VkShaderStageFlags shaderStages) {
|
||||
VkPipelineStageFlags result = 0;
|
||||
if (shaderStages & VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
result |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||
if (shaderStages & VK_SHADER_STAGE_VERTEX_BIT)
|
||||
result |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
|
||||
if (shaderStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
|
||||
result |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT;
|
||||
if (shaderStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
|
||||
result |= VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
|
||||
if (shaderStages & VK_SHADER_STAGE_GEOMETRY_BIT)
|
||||
result |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
|
||||
if (shaderStages & VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
result |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
16
src/dxvk/dxvk_util.h
Normal file
16
src/dxvk/dxvk_util.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxvk_include.h"
|
||||
|
||||
namespace dxvk::util {
|
||||
|
||||
/**
|
||||
* \brief Gets pipeline stage flags for shader stages
|
||||
*
|
||||
* \param [in] shaderStages Shader stage flags
|
||||
* \returns Corresponding pipeline stage flags
|
||||
*/
|
||||
VkPipelineStageFlags pipelineStages(
|
||||
VkShaderStageFlags shaderStages);
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
dxvk_src = files([
|
||||
'dxvk_adapter.cpp',
|
||||
'dxvk_barrier.cpp',
|
||||
'dxvk_buffer.cpp',
|
||||
'dxvk_cmdlist.cpp',
|
||||
'dxvk_compute.cpp',
|
||||
@ -21,6 +22,7 @@ dxvk_src = files([
|
||||
'dxvk_surface.cpp',
|
||||
'dxvk_swapchain.cpp',
|
||||
'dxvk_sync.cpp',
|
||||
'dxvk_util.cpp',
|
||||
|
||||
'spirv/dxvk_spirv_code_buffer.cpp',
|
||||
|
||||
|
@ -9,11 +9,20 @@ namespace dxvk {
|
||||
DxvkSpirvCodeBuffer::~DxvkSpirvCodeBuffer() { }
|
||||
|
||||
|
||||
DxvkSpirvCodeBuffer::DxvkSpirvCodeBuffer(
|
||||
std::basic_istream<uint32_t>& stream)
|
||||
: m_code(
|
||||
std::istreambuf_iterator<uint32_t>(stream),
|
||||
std::istreambuf_iterator<uint32_t>()) { }
|
||||
DxvkSpirvCodeBuffer::DxvkSpirvCodeBuffer(std::istream&& stream) {
|
||||
stream.ignore(std::numeric_limits<std::streamsize>::max());
|
||||
std::streamsize length = stream.gcount();
|
||||
stream.clear();
|
||||
stream.seekg(0, std::ios_base::beg);
|
||||
|
||||
std::vector<char> buffer(length);
|
||||
stream.read(buffer.data(), length);
|
||||
buffer.resize(stream.gcount());
|
||||
|
||||
m_code.resize(buffer.size() / sizeof(uint32_t));
|
||||
std::memcpy(reinterpret_cast<char*>(m_code.data()),
|
||||
buffer.data(), m_code.size() * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
|
||||
void DxvkSpirvCodeBuffer::append(const DxvkSpirvCodeBuffer& other) {
|
||||
@ -100,8 +109,10 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkSpirvCodeBuffer::store(std::basic_ostream<uint32_t>& stream) const {
|
||||
stream.write(m_code.data(), m_code.size());
|
||||
void DxvkSpirvCodeBuffer::store(std::ostream&& stream) const {
|
||||
stream.write(
|
||||
reinterpret_cast<const char*>(m_code.data()),
|
||||
sizeof(uint32_t) * m_code.size());
|
||||
}
|
||||
|
||||
}
|
@ -21,8 +21,7 @@ namespace dxvk {
|
||||
public:
|
||||
|
||||
DxvkSpirvCodeBuffer();
|
||||
DxvkSpirvCodeBuffer(
|
||||
std::basic_istream<uint32_t>& stream);
|
||||
DxvkSpirvCodeBuffer(std::istream&& stream);
|
||||
~DxvkSpirvCodeBuffer();
|
||||
|
||||
/**
|
||||
@ -38,7 +37,7 @@ namespace dxvk {
|
||||
* \returns Code size, in bytes
|
||||
*/
|
||||
size_t size() const {
|
||||
return m_code.size();
|
||||
return m_code.size() * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -120,7 +119,7 @@ namespace dxvk {
|
||||
* exists mostly for debugging purposes.
|
||||
* \param [in] stream Output stream
|
||||
*/
|
||||
void store(std::basic_ostream<uint32_t>& stream) const;
|
||||
void store(std::ostream&& stream) const;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -3,6 +3,9 @@
|
||||
#include <dxvk_main.h>
|
||||
#include <dxvk_surface.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
@ -26,6 +29,37 @@ public:
|
||||
m_dxvkContext (m_dxvkDevice->createContext()),
|
||||
m_dxvkCommandList (m_dxvkDevice->createCommandList()) {
|
||||
|
||||
DxvkBufferCreateInfo bufferInfo;
|
||||
bufferInfo.size = sizeof(m_testData);
|
||||
bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
bufferInfo.stages = VK_PIPELINE_STAGE_HOST_BIT
|
||||
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||
bufferInfo.access = VK_ACCESS_HOST_WRITE_BIT
|
||||
| VK_ACCESS_HOST_READ_BIT
|
||||
| VK_ACCESS_SHADER_WRITE_BIT
|
||||
| VK_ACCESS_SHADER_READ_BIT;
|
||||
|
||||
m_testBuffer = m_dxvkDevice->createBuffer(bufferInfo,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
for (size_t i = 0; i < 64; i++)
|
||||
m_testData[i] = static_cast<int>(i);
|
||||
std::memcpy(m_testBuffer->mapPtr(),
|
||||
m_testData, sizeof(m_testData));
|
||||
|
||||
DxvkResourceSlot computeBufferSlot;
|
||||
computeBufferSlot.mode.set(
|
||||
DxvkResourceModeBit::Read,
|
||||
DxvkResourceModeBit::Write);
|
||||
computeBufferSlot.type = DxvkResourceType::StorageBuffer;
|
||||
computeBufferSlot.slot = 0;
|
||||
|
||||
DxvkSpirvCodeBuffer code(std::ifstream("comp.spv", std::ios::binary));
|
||||
code.store(std::ofstream("comp.2.spv", std::ios::binary));
|
||||
|
||||
m_compShader = m_dxvkDevice->createShader(
|
||||
VK_SHADER_STAGE_COMPUTE_BIT, std::move(code),
|
||||
1, &computeBufferSlot);
|
||||
}
|
||||
|
||||
~TriangleApp() {
|
||||
@ -40,7 +74,7 @@ public:
|
||||
auto fbSize = fb->size();
|
||||
|
||||
m_dxvkContext->beginRecording(m_dxvkCommandList);
|
||||
m_dxvkContext->setFramebuffer(fb);
|
||||
m_dxvkContext->bindFramebuffer(fb);
|
||||
|
||||
VkClearAttachment clearAttachment;
|
||||
clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
@ -58,6 +92,13 @@ public:
|
||||
m_dxvkContext->clearRenderTarget(
|
||||
clearAttachment,
|
||||
clearArea);
|
||||
m_dxvkContext->bindShader(
|
||||
VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
m_compShader);
|
||||
m_dxvkContext->bindStorageBuffer(
|
||||
VK_SHADER_STAGE_COMPUTE_BIT, 0,
|
||||
m_testBuffer, 0, sizeof(m_testData));
|
||||
m_dxvkContext->dispatch(1, 1, 1);
|
||||
m_dxvkContext->endRecording();
|
||||
|
||||
auto fence = m_dxvkDevice->submitCommandList(
|
||||
@ -76,9 +117,13 @@ private:
|
||||
Rc<DxvkContext> m_dxvkContext;
|
||||
Rc<DxvkCommandList> m_dxvkCommandList;
|
||||
|
||||
Rc<DxvkBuffer> m_testBuffer;
|
||||
Rc<DxvkShader> m_compShader;
|
||||
Rc<DxvkShader> m_vertShader;
|
||||
Rc<DxvkShader> m_fragShader;
|
||||
|
||||
int m_testData[64];
|
||||
|
||||
};
|
||||
|
||||
LRESULT CALLBACK WindowProc(HWND hWnd,
|
||||
|
Loading…
Reference in New Issue
Block a user