2017-10-10 23:32:13 +02:00
|
|
|
#include "dxvk_context.h"
|
|
|
|
#include "dxvk_main.h"
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
|
|
|
DxvkContext::DxvkContext(const Rc<vk::DeviceFn>& vkd)
|
2017-10-11 00:27:33 +02:00
|
|
|
: m_vkd(vkd) {
|
|
|
|
TRACE(this);
|
|
|
|
}
|
2017-10-10 23:32:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
DxvkContext::~DxvkContext() {
|
2017-10-11 00:27:33 +02:00
|
|
|
TRACE(this);
|
2017-10-10 23:32:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkContext::beginRecording(
|
|
|
|
const Rc<DxvkCommandList>& cmdList) {
|
2017-10-11 00:27:33 +02:00
|
|
|
TRACE(this, cmdList);
|
2017-10-10 23:32:13 +02:00
|
|
|
m_commandList = cmdList;
|
|
|
|
m_commandList->beginRecording();
|
2017-10-13 03:19:23 +02:00
|
|
|
|
|
|
|
// 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);
|
2017-10-10 23:32:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool DxvkContext::endRecording() {
|
2017-10-11 00:27:33 +02:00
|
|
|
TRACE(this);
|
2017-10-11 23:29:05 +02:00
|
|
|
|
2017-10-13 03:19:23 +02:00
|
|
|
// Any currently active render pass must be
|
|
|
|
// ended before finalizing the command buffer.
|
|
|
|
if (m_state.g.flags.test(DxvkGraphicsPipelineBit::RenderPassBound))
|
2017-10-11 23:29:05 +02:00
|
|
|
this->endRenderPass();
|
|
|
|
|
|
|
|
// Finalize the command list
|
2017-10-10 23:32:13 +02:00
|
|
|
m_commandList->endRecording();
|
|
|
|
m_commandList = nullptr;
|
|
|
|
return true;
|
|
|
|
}
|
2017-10-11 23:29:05 +02:00
|
|
|
|
|
|
|
|
|
|
|
void DxvkContext::clearRenderTarget(
|
|
|
|
const VkClearAttachment& attachment,
|
|
|
|
const VkClearRect& clearArea) {
|
2017-10-13 03:19:23 +02:00
|
|
|
this->flushGraphicsState();
|
2017-10-10 23:32:13 +02:00
|
|
|
|
2017-10-11 23:29:05 +02:00
|
|
|
m_vkd->vkCmdClearAttachments(
|
|
|
|
m_commandList->handle(),
|
|
|
|
1, &attachment,
|
|
|
|
1, &clearArea);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-13 03:19:23 +02:00
|
|
|
void DxvkContext::dispatch(
|
|
|
|
uint32_t wgCountX,
|
|
|
|
uint32_t wgCountY,
|
|
|
|
uint32_t wgCountZ) {
|
|
|
|
this->flushComputeState();
|
|
|
|
|
|
|
|
m_vkd->vkCmdDispatch(
|
|
|
|
m_commandList->handle(),
|
|
|
|
wgCountX, wgCountY, wgCountZ);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-11 23:29:05 +02:00
|
|
|
void DxvkContext::draw(
|
|
|
|
uint32_t vertexCount,
|
|
|
|
uint32_t instanceCount,
|
|
|
|
uint32_t firstVertex,
|
|
|
|
uint32_t firstInstance) {
|
2017-10-13 03:19:23 +02:00
|
|
|
this->flushGraphicsState();
|
|
|
|
|
2017-10-11 23:29:05 +02:00
|
|
|
m_vkd->vkCmdDraw(
|
|
|
|
m_commandList->handle(),
|
|
|
|
vertexCount,
|
|
|
|
instanceCount,
|
|
|
|
firstVertex,
|
|
|
|
firstInstance);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkContext::drawIndexed(
|
|
|
|
uint32_t indexCount,
|
|
|
|
uint32_t instanceCount,
|
|
|
|
uint32_t firstIndex,
|
|
|
|
uint32_t vertexOffset,
|
|
|
|
uint32_t firstInstance) {
|
2017-10-13 03:19:23 +02:00
|
|
|
this->flushGraphicsState();
|
|
|
|
|
2017-10-11 23:29:05 +02:00
|
|
|
m_vkd->vkCmdDrawIndexed(
|
|
|
|
m_commandList->handle(),
|
|
|
|
indexCount,
|
|
|
|
instanceCount,
|
|
|
|
firstIndex,
|
|
|
|
vertexOffset,
|
|
|
|
firstInstance);
|
|
|
|
}
|
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
|
|
|
|
void DxvkContext::setFramebuffer(
|
|
|
|
const Rc<DxvkFramebuffer>& fb) {
|
2017-10-11 00:27:33 +02:00
|
|
|
TRACE(this, fb);
|
|
|
|
|
2017-10-13 03:19:23 +02:00
|
|
|
if (m_state.g.fb != fb) {
|
|
|
|
m_state.g.fb = fb;
|
2017-10-11 23:29:05 +02:00
|
|
|
|
2017-10-13 03:19:23 +02:00
|
|
|
if (m_state.g.flags.test(
|
|
|
|
DxvkGraphicsPipelineBit::RenderPassBound))
|
|
|
|
this->endRenderPass();
|
2017-10-11 23:29:05 +02:00
|
|
|
}
|
|
|
|
}
|
2017-10-13 03:19:23 +02:00
|
|
|
|
2017-10-11 23:29:05 +02:00
|
|
|
|
|
|
|
void DxvkContext::setShader(
|
|
|
|
VkShaderStageFlagBits stage,
|
|
|
|
const Rc<DxvkShader>& shader) {
|
|
|
|
TRACE(this, stage, shader);
|
|
|
|
|
2017-10-13 03:19:23 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2017-10-11 23:29:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-13 03:19:23 +02:00
|
|
|
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());
|
|
|
|
}
|
2017-10-11 23:29:05 +02:00
|
|
|
|
2017-10-13 03:19:23 +02:00
|
|
|
m_state.c.flags.clr(
|
|
|
|
DxvkComputePipelineBit::PipelineDirty,
|
|
|
|
DxvkComputePipelineBit::DirtyResources);
|
2017-10-11 23:29:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-13 03:19:23 +02:00
|
|
|
void DxvkContext::flushGraphicsState() {
|
|
|
|
if (!m_state.g.flags.test(DxvkGraphicsPipelineBit::RenderPassBound))
|
2017-10-11 23:29:05 +02:00
|
|
|
this->beginRenderPass();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkContext::beginRenderPass() {
|
|
|
|
TRACE(this);
|
|
|
|
|
2017-10-13 03:19:23 +02:00
|
|
|
DxvkFramebufferSize fbsize
|
|
|
|
= m_state.g.fb->size();
|
2017-10-11 23:29:05 +02:00
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
VkRenderPassBeginInfo info;
|
|
|
|
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
|
|
|
info.pNext = nullptr;
|
2017-10-13 03:19:23 +02:00
|
|
|
info.renderPass = m_state.g.fb->renderPass();
|
|
|
|
info.framebuffer = m_state.g.fb->handle();
|
2017-10-11 23:29:05 +02:00
|
|
|
info.renderArea = VkRect2D { { 0, 0 }, { fbsize.width, fbsize.height } };
|
2017-10-10 23:32:13 +02:00
|
|
|
info.clearValueCount = 0;
|
|
|
|
info.pClearValues = nullptr;
|
|
|
|
|
2017-10-13 03:19:23 +02:00
|
|
|
m_vkd->vkCmdBeginRenderPass(m_commandList->handle(), &info, VK_SUBPASS_CONTENTS_INLINE);
|
|
|
|
m_state.g.flags.set(DxvkGraphicsPipelineBit::RenderPassBound);
|
2017-10-11 23:29:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkContext::endRenderPass() {
|
|
|
|
TRACE(this);
|
|
|
|
|
|
|
|
m_vkd->vkCmdEndRenderPass(m_commandList->handle());
|
2017-10-13 03:19:23 +02:00
|
|
|
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;
|
|
|
|
}
|
2017-10-10 23:32:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|