mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-27 04:54:15 +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
|
/// Buffer usage flags
|
||||||
VkBufferUsageFlags usage;
|
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);
|
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 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:
|
private:
|
||||||
|
|
||||||
Rc<vk::DeviceFn> m_vkd;
|
Rc<vk::DeviceFn> m_vkd;
|
||||||
|
@ -6,6 +6,7 @@ namespace dxvk {
|
|||||||
const Rc<vk::DeviceFn>& vkd,
|
const Rc<vk::DeviceFn>& vkd,
|
||||||
const Rc<DxvkShader>& shader)
|
const Rc<DxvkShader>& shader)
|
||||||
: m_vkd(vkd) {
|
: m_vkd(vkd) {
|
||||||
|
TRACE(this, shader);
|
||||||
|
|
||||||
std::vector<VkDescriptorSetLayoutBinding> bindings;
|
std::vector<VkDescriptorSetLayoutBinding> bindings;
|
||||||
|
|
||||||
@ -80,6 +81,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
DxvkComputePipeline::~DxvkComputePipeline() {
|
DxvkComputePipeline::~DxvkComputePipeline() {
|
||||||
|
TRACE(this);
|
||||||
this->destroyObjects();
|
this->destroyObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,11 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
DxvkContext::DxvkContext(const Rc<DxvkDevice>& device)
|
DxvkContext::DxvkContext(
|
||||||
: m_device(device) {
|
const Rc<DxvkDevice>& device,
|
||||||
|
const Rc<DxvkPipelineManager>& pipeMgr)
|
||||||
|
: m_device (device),
|
||||||
|
m_pipeMgr (pipeMgr) {
|
||||||
TRACE(this, device);
|
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(
|
void DxvkContext::clearRenderTarget(
|
||||||
const VkClearAttachment& attachment,
|
const VkClearAttachment& attachment,
|
||||||
const VkClearRect& clearArea) {
|
const VkClearRect& clearArea) {
|
||||||
@ -67,6 +121,8 @@ namespace dxvk {
|
|||||||
uint32_t wgCountX,
|
uint32_t wgCountX,
|
||||||
uint32_t wgCountY,
|
uint32_t wgCountY,
|
||||||
uint32_t wgCountZ) {
|
uint32_t wgCountZ) {
|
||||||
|
TRACE(this, wgCountX, wgCountY, wgCountZ);
|
||||||
|
this->endRenderPass();
|
||||||
this->flushComputeState();
|
this->flushComputeState();
|
||||||
|
|
||||||
m_cmd->cmdDispatch(
|
m_cmd->cmdDispatch(
|
||||||
@ -79,6 +135,8 @@ namespace dxvk {
|
|||||||
uint32_t instanceCount,
|
uint32_t instanceCount,
|
||||||
uint32_t firstVertex,
|
uint32_t firstVertex,
|
||||||
uint32_t firstInstance) {
|
uint32_t firstInstance) {
|
||||||
|
TRACE(this, vertexCount, instanceCount,
|
||||||
|
firstVertex, firstInstance);
|
||||||
this->flushGraphicsState();
|
this->flushGraphicsState();
|
||||||
|
|
||||||
m_cmd->cmdDraw(
|
m_cmd->cmdDraw(
|
||||||
@ -93,6 +151,8 @@ namespace dxvk {
|
|||||||
uint32_t firstIndex,
|
uint32_t firstIndex,
|
||||||
uint32_t vertexOffset,
|
uint32_t vertexOffset,
|
||||||
uint32_t firstInstance) {
|
uint32_t firstInstance) {
|
||||||
|
TRACE(this, indexCount, instanceCount,
|
||||||
|
firstIndex, vertexOffset, firstInstance);
|
||||||
this->flushGraphicsState();
|
this->flushGraphicsState();
|
||||||
|
|
||||||
m_cmd->cmdDrawIndexed(
|
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() {
|
void DxvkContext::flushComputeState() {
|
||||||
if (m_state.c.flags.test(DxvkComputePipelineBit::PipelineDirty)
|
if (m_state.c.flags.test(DxvkComputePipelineBit::PipelineDirty)) {
|
||||||
&& m_state.c.pipeline != nullptr) {
|
m_state.c.pipeline = m_pipeMgr->getComputePipeline(m_state.c.cs.shader);
|
||||||
m_cmd->cmdBindPipeline(
|
|
||||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
if (m_state.c.pipeline != nullptr) {
|
||||||
m_state.c.pipeline->getPipelineHandle());
|
m_cmd->cmdBindPipeline(
|
||||||
|
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||||
|
m_state.c.pipeline->getPipelineHandle());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_state.c.flags.clr(
|
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) {
|
DxvkShaderState* DxvkContext::getShaderState(VkShaderStageFlagBits stage) {
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case VK_SHADER_STAGE_VERTEX_BIT:
|
case VK_SHADER_STAGE_VERTEX_BIT:
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "dxvk_barrier.h"
|
||||||
#include "dxvk_cmdlist.h"
|
#include "dxvk_cmdlist.h"
|
||||||
#include "dxvk_context_state.h"
|
#include "dxvk_context_state.h"
|
||||||
#include "dxvk_deferred.h"
|
#include "dxvk_deferred.h"
|
||||||
|
#include "dxvk_pipemgr.h"
|
||||||
|
#include "dxvk_util.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
@ -18,7 +21,8 @@ namespace dxvk {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
DxvkContext(
|
DxvkContext(
|
||||||
const Rc<DxvkDevice>& device);
|
const Rc<DxvkDevice>& device,
|
||||||
|
const Rc<DxvkPipelineManager>& pipeMgr);
|
||||||
~DxvkContext();
|
~DxvkContext();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,6 +55,41 @@ namespace dxvk {
|
|||||||
*/
|
*/
|
||||||
bool endRecording();
|
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
|
* \brief Clears an active render target
|
||||||
*
|
*
|
||||||
@ -103,30 +142,10 @@ namespace dxvk {
|
|||||||
uint32_t vertexOffset,
|
uint32_t vertexOffset,
|
||||||
uint32_t firstInstance);
|
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:
|
private:
|
||||||
|
|
||||||
const Rc<DxvkDevice> m_device;
|
const Rc<DxvkDevice> m_device;
|
||||||
|
const Rc<DxvkPipelineManager> m_pipeMgr;
|
||||||
|
|
||||||
Rc<DxvkRecorder> m_cmd;
|
Rc<DxvkRecorder> m_cmd;
|
||||||
DxvkContextState m_state;
|
DxvkContextState m_state;
|
||||||
@ -137,9 +156,19 @@ namespace dxvk {
|
|||||||
void beginRenderPass();
|
void beginRenderPass();
|
||||||
void endRenderPass();
|
void endRenderPass();
|
||||||
|
|
||||||
|
void setPipelineDirty(VkShaderStageFlagBits stage);
|
||||||
|
void setResourcesDirty(VkShaderStageFlagBits stage);
|
||||||
|
|
||||||
|
void shaderResourceBarriers(
|
||||||
|
DxvkBarrierSet& barriers,
|
||||||
|
VkShaderStageFlagBits stage);
|
||||||
|
|
||||||
DxvkShaderState* getShaderState(
|
DxvkShaderState* getShaderState(
|
||||||
VkShaderStageFlagBits stage);
|
VkShaderStageFlagBits stage);
|
||||||
|
|
||||||
|
VkPipelineStageFlags pipelineStage(
|
||||||
|
VkShaderStageFlags shaderStage) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "dxvk_buffer.h"
|
||||||
#include "dxvk_compute.h"
|
#include "dxvk_compute.h"
|
||||||
#include "dxvk_framebuffer.h"
|
#include "dxvk_framebuffer.h"
|
||||||
|
#include "dxvk_image.h"
|
||||||
#include "dxvk_limits.h"
|
#include "dxvk_limits.h"
|
||||||
#include "dxvk_shader.h"
|
#include "dxvk_shader.h"
|
||||||
|
|
||||||
@ -48,7 +50,10 @@ namespace dxvk {
|
|||||||
* buffers, storage buffers and storage images.
|
* buffers, storage buffers and storage images.
|
||||||
*/
|
*/
|
||||||
struct DxvkShaderState {
|
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(
|
DxvkDevice::DxvkDevice(
|
||||||
const Rc<DxvkAdapter>& adapter,
|
const Rc<DxvkAdapter>& adapter,
|
||||||
const Rc<vk::DeviceFn>& vkd)
|
const Rc<vk::DeviceFn>& vkd)
|
||||||
: m_adapter (adapter),
|
: m_adapter (adapter),
|
||||||
m_vkd (vkd),
|
m_vkd (vkd),
|
||||||
m_memory (adapter, vkd),
|
m_memory (new DxvkMemoryAllocator(adapter, vkd)),
|
||||||
m_renderPassPool(vkd) {
|
m_renderPassPool (new DxvkRenderPassPool (vkd)),
|
||||||
|
m_pipelineManager (new DxvkPipelineManager(vkd)) {
|
||||||
TRACE(this, adapter);
|
TRACE(this, adapter);
|
||||||
|
|
||||||
m_vkd->vkGetDeviceQueue(m_vkd->device(),
|
m_vkd->vkGetDeviceQueue(m_vkd->device(),
|
||||||
@ -23,6 +24,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
DxvkDevice::~DxvkDevice() {
|
DxvkDevice::~DxvkDevice() {
|
||||||
TRACE(this);
|
TRACE(this);
|
||||||
|
m_pipelineManager = nullptr;
|
||||||
|
m_renderPassPool = nullptr;
|
||||||
|
m_memory = nullptr;
|
||||||
|
|
||||||
m_vkd->vkDeviceWaitIdle(m_vkd->device());
|
m_vkd->vkDeviceWaitIdle(m_vkd->device());
|
||||||
m_vkd->vkDestroyDevice(m_vkd->device(), nullptr);
|
m_vkd->vkDestroyDevice(m_vkd->device(), nullptr);
|
||||||
}
|
}
|
||||||
@ -35,14 +40,14 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
Rc<DxvkContext> DxvkDevice::createContext() {
|
Rc<DxvkContext> DxvkDevice::createContext() {
|
||||||
return new DxvkContext(this);
|
return new DxvkContext(this, m_pipelineManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkFramebuffer> DxvkDevice::createFramebuffer(
|
Rc<DxvkFramebuffer> DxvkDevice::createFramebuffer(
|
||||||
const DxvkRenderTargets& renderTargets) {
|
const DxvkRenderTargets& renderTargets) {
|
||||||
auto format = renderTargets.renderPassFormat();
|
auto format = renderTargets.renderPassFormat();
|
||||||
auto renderPass = m_renderPassPool.getRenderPass(format);
|
auto renderPass = m_renderPassPool->getRenderPass(format);
|
||||||
return new DxvkFramebuffer(m_vkd, renderPass, renderTargets);
|
return new DxvkFramebuffer(m_vkd, renderPass, renderTargets);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +56,7 @@ namespace dxvk {
|
|||||||
const DxvkBufferCreateInfo& createInfo,
|
const DxvkBufferCreateInfo& createInfo,
|
||||||
VkMemoryPropertyFlags memoryType) {
|
VkMemoryPropertyFlags memoryType) {
|
||||||
return new DxvkBuffer(m_vkd,
|
return new DxvkBuffer(m_vkd,
|
||||||
createInfo, m_memory, memoryType);
|
createInfo, *m_memory, memoryType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "dxvk_context.h"
|
#include "dxvk_context.h"
|
||||||
#include "dxvk_framebuffer.h"
|
#include "dxvk_framebuffer.h"
|
||||||
#include "dxvk_memory.h"
|
#include "dxvk_memory.h"
|
||||||
|
#include "dxvk_pipemgr.h"
|
||||||
#include "dxvk_renderpass.h"
|
#include "dxvk_renderpass.h"
|
||||||
#include "dxvk_shader.h"
|
#include "dxvk_shader.h"
|
||||||
#include "dxvk_swapchain.h"
|
#include "dxvk_swapchain.h"
|
||||||
@ -179,13 +180,13 @@ namespace dxvk {
|
|||||||
Rc<DxvkAdapter> m_adapter;
|
Rc<DxvkAdapter> m_adapter;
|
||||||
Rc<vk::DeviceFn> m_vkd;
|
Rc<vk::DeviceFn> m_vkd;
|
||||||
|
|
||||||
DxvkMemoryAllocator m_memory;
|
Rc<DxvkMemoryAllocator> m_memory;
|
||||||
DxvkRenderPassPool m_renderPassPool;
|
Rc<DxvkRenderPassPool> m_renderPassPool;
|
||||||
|
Rc<DxvkPipelineManager> m_pipelineManager;
|
||||||
|
|
||||||
VkQueue m_graphicsQueue;
|
VkQueue m_graphicsQueue;
|
||||||
VkQueue m_presentQueue;
|
VkQueue m_presentQueue;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -2,17 +2,17 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
size_t DxvkGraphicsPipelineState::hash() const {
|
size_t DxvkGraphicsPipelineStateInfo::hash() const {
|
||||||
// TODO implement
|
// TODO implement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DxvkGraphicsPipelineState::operator == (const DxvkGraphicsPipelineState& other) const {
|
bool DxvkGraphicsPipelineStateInfo::operator == (const DxvkGraphicsPipelineStateInfo& other) const {
|
||||||
// TODO implement
|
// TODO implement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DxvkGraphicsPipelineState::operator != (const DxvkGraphicsPipelineState& other) const {
|
bool DxvkGraphicsPipelineStateInfo::operator != (const DxvkGraphicsPipelineStateInfo& other) const {
|
||||||
return !this->operator == (other);
|
return !this->operator == (other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
VkPipeline DxvkGraphicsPipeline::getPipelineHandle(
|
VkPipeline DxvkGraphicsPipeline::getPipelineHandle(
|
||||||
const DxvkGraphicsPipelineState& state) {
|
const DxvkGraphicsPipelineStateInfo& state) {
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
auto pair = m_pipelines.find(state);
|
auto pair = m_pipelines.find(state);
|
||||||
@ -50,7 +50,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
VkPipeline DxvkGraphicsPipeline::compilePipeline(
|
VkPipeline DxvkGraphicsPipeline::compilePipeline(
|
||||||
const DxvkGraphicsPipelineState& state) const {
|
const DxvkGraphicsPipelineStateInfo& state) const {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,13 +9,13 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
struct DxvkGraphicsPipelineState {
|
struct DxvkGraphicsPipelineStateInfo {
|
||||||
VkRenderPass renderPass;
|
VkRenderPass renderPass;
|
||||||
|
|
||||||
size_t hash() const;
|
size_t hash() const;
|
||||||
|
|
||||||
bool operator == (const DxvkGraphicsPipelineState& other) const;
|
bool operator == (const DxvkGraphicsPipelineStateInfo& other) const;
|
||||||
bool operator != (const DxvkGraphicsPipelineState& other) const;
|
bool operator != (const DxvkGraphicsPipelineStateInfo& other) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,7 +43,7 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VkPipeline getPipelineHandle(
|
VkPipeline getPipelineHandle(
|
||||||
const DxvkGraphicsPipelineState& state);
|
const DxvkGraphicsPipelineStateInfo& state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -60,11 +60,11 @@ namespace dxvk {
|
|||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
|
|
||||||
std::unordered_map<
|
std::unordered_map<
|
||||||
DxvkGraphicsPipelineState,
|
DxvkGraphicsPipelineStateInfo,
|
||||||
VkPipeline, DxvkHash> m_pipelines;
|
VkPipeline, DxvkHash> m_pipelines;
|
||||||
|
|
||||||
VkPipeline compilePipeline(
|
VkPipeline compilePipeline(
|
||||||
const DxvkGraphicsPipelineState& state) const;
|
const DxvkGraphicsPipelineStateInfo& state) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ namespace dxvk {
|
|||||||
* Allocates device memory for Vulkan resources.
|
* Allocates device memory for Vulkan resources.
|
||||||
* Memory objects will be destroyed automatically.
|
* Memory objects will be destroyed automatically.
|
||||||
*/
|
*/
|
||||||
class DxvkMemoryAllocator {
|
class DxvkMemoryAllocator : public RcObject {
|
||||||
friend class DxvkMemory;
|
friend class DxvkMemory;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -14,8 +14,9 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkComputePipeline> DxvkPipelineManager::getComputePipeline(
|
Rc<DxvkComputePipeline> DxvkPipelineManager::getComputePipeline(const Rc<DxvkShader>& cs) {
|
||||||
const Rc<DxvkShader>& cs) {
|
if (cs == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
DxvkPipelineKey<1> key;
|
DxvkPipelineKey<1> key;
|
||||||
key.setShader(0, cs);
|
key.setShader(0, cs);
|
||||||
@ -38,6 +39,8 @@ namespace dxvk {
|
|||||||
const Rc<DxvkShader>& tes,
|
const Rc<DxvkShader>& tes,
|
||||||
const Rc<DxvkShader>& gs,
|
const Rc<DxvkShader>& gs,
|
||||||
const Rc<DxvkShader>& fs) {
|
const Rc<DxvkShader>& fs) {
|
||||||
|
if (vs == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
DxvkPipelineKey<5> key;
|
DxvkPipelineKey<5> key;
|
||||||
key.setShader(0, vs);
|
key.setShader(0, vs);
|
||||||
|
@ -73,6 +73,7 @@ namespace dxvk {
|
|||||||
* shader. If no such pipeline object exists, a new
|
* shader. If no such pipeline object exists, a new
|
||||||
* one will be created.
|
* one will be created.
|
||||||
* \param [in] cs Compute shader
|
* \param [in] cs Compute shader
|
||||||
|
* \returns Compute pipeline
|
||||||
*/
|
*/
|
||||||
Rc<DxvkComputePipeline> getComputePipeline(
|
Rc<DxvkComputePipeline> getComputePipeline(
|
||||||
const Rc<DxvkShader>& cs);
|
const Rc<DxvkShader>& cs);
|
||||||
|
@ -61,6 +61,17 @@ namespace dxvk {
|
|||||||
|
|
||||||
virtual void cmdEndRenderPass() = 0;
|
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
|
* Thread-safe class that manages the render pass
|
||||||
* objects that are used within an application.
|
* objects that are used within an application.
|
||||||
*/
|
*/
|
||||||
class DxvkRenderPassPool {
|
class DxvkRenderPassPool : public RcObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -8,6 +8,19 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
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
|
* \brief Shader resource type
|
||||||
*
|
*
|
||||||
@ -27,6 +40,7 @@ namespace dxvk {
|
|||||||
* \brief Resource slot
|
* \brief Resource slot
|
||||||
*/
|
*/
|
||||||
struct DxvkResourceSlot{
|
struct DxvkResourceSlot{
|
||||||
|
DxvkResourceMode mode;
|
||||||
DxvkResourceType type;
|
DxvkResourceType type;
|
||||||
uint32_t slot;
|
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_src = files([
|
||||||
'dxvk_adapter.cpp',
|
'dxvk_adapter.cpp',
|
||||||
|
'dxvk_barrier.cpp',
|
||||||
'dxvk_buffer.cpp',
|
'dxvk_buffer.cpp',
|
||||||
'dxvk_cmdlist.cpp',
|
'dxvk_cmdlist.cpp',
|
||||||
'dxvk_compute.cpp',
|
'dxvk_compute.cpp',
|
||||||
@ -21,6 +22,7 @@ dxvk_src = files([
|
|||||||
'dxvk_surface.cpp',
|
'dxvk_surface.cpp',
|
||||||
'dxvk_swapchain.cpp',
|
'dxvk_swapchain.cpp',
|
||||||
'dxvk_sync.cpp',
|
'dxvk_sync.cpp',
|
||||||
|
'dxvk_util.cpp',
|
||||||
|
|
||||||
'spirv/dxvk_spirv_code_buffer.cpp',
|
'spirv/dxvk_spirv_code_buffer.cpp',
|
||||||
|
|
||||||
|
@ -9,11 +9,20 @@ namespace dxvk {
|
|||||||
DxvkSpirvCodeBuffer::~DxvkSpirvCodeBuffer() { }
|
DxvkSpirvCodeBuffer::~DxvkSpirvCodeBuffer() { }
|
||||||
|
|
||||||
|
|
||||||
DxvkSpirvCodeBuffer::DxvkSpirvCodeBuffer(
|
DxvkSpirvCodeBuffer::DxvkSpirvCodeBuffer(std::istream&& stream) {
|
||||||
std::basic_istream<uint32_t>& stream)
|
stream.ignore(std::numeric_limits<std::streamsize>::max());
|
||||||
: m_code(
|
std::streamsize length = stream.gcount();
|
||||||
std::istreambuf_iterator<uint32_t>(stream),
|
stream.clear();
|
||||||
std::istreambuf_iterator<uint32_t>()) { }
|
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) {
|
void DxvkSpirvCodeBuffer::append(const DxvkSpirvCodeBuffer& other) {
|
||||||
@ -100,8 +109,10 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkSpirvCodeBuffer::store(std::basic_ostream<uint32_t>& stream) const {
|
void DxvkSpirvCodeBuffer::store(std::ostream&& stream) const {
|
||||||
stream.write(m_code.data(), m_code.size());
|
stream.write(
|
||||||
|
reinterpret_cast<const char*>(m_code.data()),
|
||||||
|
sizeof(uint32_t) * m_code.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -21,8 +21,7 @@ namespace dxvk {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
DxvkSpirvCodeBuffer();
|
DxvkSpirvCodeBuffer();
|
||||||
DxvkSpirvCodeBuffer(
|
DxvkSpirvCodeBuffer(std::istream&& stream);
|
||||||
std::basic_istream<uint32_t>& stream);
|
|
||||||
~DxvkSpirvCodeBuffer();
|
~DxvkSpirvCodeBuffer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,7 +37,7 @@ namespace dxvk {
|
|||||||
* \returns Code size, in bytes
|
* \returns Code size, in bytes
|
||||||
*/
|
*/
|
||||||
size_t size() const {
|
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.
|
* exists mostly for debugging purposes.
|
||||||
* \param [in] stream Output stream
|
* \param [in] stream Output stream
|
||||||
*/
|
*/
|
||||||
void store(std::basic_ostream<uint32_t>& stream) const;
|
void store(std::ostream&& stream) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
#include <dxvk_main.h>
|
#include <dxvk_main.h>
|
||||||
#include <dxvk_surface.h>
|
#include <dxvk_surface.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
|
|
||||||
@ -26,6 +29,37 @@ public:
|
|||||||
m_dxvkContext (m_dxvkDevice->createContext()),
|
m_dxvkContext (m_dxvkDevice->createContext()),
|
||||||
m_dxvkCommandList (m_dxvkDevice->createCommandList()) {
|
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() {
|
~TriangleApp() {
|
||||||
@ -40,7 +74,7 @@ public:
|
|||||||
auto fbSize = fb->size();
|
auto fbSize = fb->size();
|
||||||
|
|
||||||
m_dxvkContext->beginRecording(m_dxvkCommandList);
|
m_dxvkContext->beginRecording(m_dxvkCommandList);
|
||||||
m_dxvkContext->setFramebuffer(fb);
|
m_dxvkContext->bindFramebuffer(fb);
|
||||||
|
|
||||||
VkClearAttachment clearAttachment;
|
VkClearAttachment clearAttachment;
|
||||||
clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
@ -58,6 +92,13 @@ public:
|
|||||||
m_dxvkContext->clearRenderTarget(
|
m_dxvkContext->clearRenderTarget(
|
||||||
clearAttachment,
|
clearAttachment,
|
||||||
clearArea);
|
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();
|
m_dxvkContext->endRecording();
|
||||||
|
|
||||||
auto fence = m_dxvkDevice->submitCommandList(
|
auto fence = m_dxvkDevice->submitCommandList(
|
||||||
@ -76,9 +117,13 @@ private:
|
|||||||
Rc<DxvkContext> m_dxvkContext;
|
Rc<DxvkContext> m_dxvkContext;
|
||||||
Rc<DxvkCommandList> m_dxvkCommandList;
|
Rc<DxvkCommandList> m_dxvkCommandList;
|
||||||
|
|
||||||
|
Rc<DxvkBuffer> m_testBuffer;
|
||||||
|
Rc<DxvkShader> m_compShader;
|
||||||
Rc<DxvkShader> m_vertShader;
|
Rc<DxvkShader> m_vertShader;
|
||||||
Rc<DxvkShader> m_fragShader;
|
Rc<DxvkShader> m_fragShader;
|
||||||
|
|
||||||
|
int m_testData[64];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
LRESULT CALLBACK WindowProc(HWND hWnd,
|
LRESULT CALLBACK WindowProc(HWND hWnd,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user