383 lines
12 KiB
C++
383 lines
12 KiB
C++
#include "../vulkan_state.h"
|
|
#include "../commands.h"
|
|
#include "materialsystem/imaterialsystem.h"
|
|
#include "tier0/platform.h"
|
|
#include "tier1/utlvector.h"
|
|
|
|
|
|
DECLARE_VULKAN_COMMAND(ClearColor)
|
|
{
|
|
|
|
CVkImage *pImg;
|
|
|
|
VkClearColorValue color = {.float32 = {r,g,b,a}};
|
|
VkImageSubresourceRange range = {
|
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
.levelCount = 1,
|
|
.layerCount = 1,
|
|
};
|
|
vkCmdClearColorImage(hCommandBuffer, ((CVkImage*)VulkanGetObject(stImage, iCurrentFrame))->m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &range);
|
|
}
|
|
|
|
DECLARE_VULKAN_COMMAND(Begin)
|
|
{
|
|
if (vkCmdBeginRendering || vkCmdBeginRenderingKHR)
|
|
{
|
|
VkRenderingInfo stRenderingInfo = {};
|
|
CUtlVector<VkRenderingAttachmentInfo> attachments = {};
|
|
VkRenderingAttachmentInfo depthAttachment = {};
|
|
for (auto i: images)
|
|
{
|
|
VkRenderingAttachmentInfo a = {};
|
|
a.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
|
|
a.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
switch( i.m_eLoadMode )
|
|
{
|
|
case LOAD_MODE_DONT_CARE:
|
|
a.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
break;
|
|
case LOAD_MODE_LOAD:
|
|
a.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
|
break;
|
|
case LOAD_MODE_CLEAR:
|
|
a.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
|
a.clearValue.color.float32[0] = i.m_fClearColor[0];
|
|
a.clearValue.color.float32[1] = i.m_fClearColor[1];
|
|
a.clearValue.color.float32[2] = i.m_fClearColor[2];
|
|
a.clearValue.color.float32[3] = i.m_fClearColor[3];
|
|
break;
|
|
}
|
|
a.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
a.imageView = ((CVkImage*)VulkanGetObject(i.m_stImage, iCurrentFrame))->m_imageView;
|
|
attachments.AppendTail(a);
|
|
}
|
|
if (bDepthEnabled)
|
|
{
|
|
depthAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
|
|
depthAttachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
|
|
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
|
depthAttachment.clearValue.depthStencil.depth = stDepthImage.m_fClearDepth;
|
|
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
depthAttachment.imageView = ((CVkImage*)VulkanGetObject(stDepthImage.m_stImage, iCurrentFrame))->m_imageView;
|
|
stRenderingInfo.pDepthAttachment = &depthAttachment;
|
|
}
|
|
|
|
stRenderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
|
|
stRenderingInfo.layerCount = 1;
|
|
stRenderingInfo.colorAttachmentCount = attachments.GetSize();
|
|
stRenderingInfo.pColorAttachments = attachments.GetData();
|
|
stRenderingInfo.renderArea = (VkRect2D){0,0,nResolutionX,nResolutionY};
|
|
|
|
if (vkCmdBeginRendering)
|
|
vkCmdBeginRendering(hCommandBuffer, &stRenderingInfo);
|
|
else
|
|
vkCmdBeginRenderingKHR(hCommandBuffer, &stRenderingInfo);
|
|
}
|
|
else
|
|
{
|
|
CUtlVector<VkClearValue> colors = {};
|
|
CUtlVector<RenderImage> imgs = {};
|
|
for (auto &a: images)
|
|
{
|
|
RenderImage ri = {};
|
|
ri.pImage = (IImage*)a.m_stImage.m_pSingle;
|
|
ri.eLoadMode = a.m_eLoadMode;
|
|
ri.eStoreMode = a.m_eStoreMode;
|
|
VkClearValue ci = {};
|
|
ci.color.float32[0] = a.m_fClearColor[0];
|
|
ci.color.float32[1] = a.m_fClearColor[1];
|
|
ci.color.float32[2] = a.m_fClearColor[2];
|
|
ci.color.float32[3] = a.m_fClearColor[3];
|
|
colors.AppendTail(ci);
|
|
imgs.AppendTail(ri);
|
|
}
|
|
RenderImage depth = {};
|
|
depth.pImage = (IImage*)stDepthImage.m_stImage.m_pSingle;
|
|
depth.eLoadMode = stDepthImage.m_eLoadMode;
|
|
depth.eStoreMode = stDepthImage.m_eStoreMode;
|
|
BeginInfo bi = {};
|
|
bi.uRenderImageCount = imgs.GetSize();
|
|
bi.pRenderImages = imgs.GetData();
|
|
bi.uWidth = nResolutionX;
|
|
bi.uHeight = nResolutionY;
|
|
if (bDepthEnabled)
|
|
{
|
|
bi.pDepth = &depth;
|
|
VkClearValue ci = {};
|
|
ci.depthStencil.depth = stDepthImage.m_fClearDepth;
|
|
colors.AppendTail(ci);
|
|
}
|
|
VkRenderPass hRenderPass;
|
|
VkFramebuffer hFrameBuffer;
|
|
pMgr->CreateRenderPass(&bi, &hRenderPass, &hFrameBuffer);
|
|
|
|
VkRenderPassBeginInfo rpbi = {};
|
|
rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
|
rpbi.renderPass = hRenderPass;
|
|
rpbi.framebuffer = hFrameBuffer;
|
|
rpbi.renderArea = (VkRect2D){0,0,nResolutionX,nResolutionY};
|
|
rpbi.clearValueCount = colors.GetSize();
|
|
rpbi.pClearValues = colors.GetData();
|
|
vkCmdBeginRenderPass(hCommandBuffer, &rpbi, VK_SUBPASS_CONTENTS_INLINE);
|
|
}
|
|
}
|
|
|
|
DECLARE_VULKAN_COMMAND(End)
|
|
{
|
|
if (vkCmdEndRendering)
|
|
vkCmdEndRendering(hCommandBuffer);
|
|
else if (vkCmdEndRenderingKHR)
|
|
vkCmdEndRenderingKHR(hCommandBuffer);
|
|
else
|
|
{
|
|
vkCmdEndRenderPass(hCommandBuffer);
|
|
}
|
|
}
|
|
|
|
DECLARE_VULKAN_COMMAND(SetShader)
|
|
{
|
|
CVkShader *pS = dynamic_cast<CVkShader*>(pShader);
|
|
CVkComputeShader *pCS = dynamic_cast<CVkComputeShader*>(pShader);
|
|
if (pS)
|
|
vkCmdBindPipeline(hCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pS->m_hPipeline);
|
|
if (pCS)
|
|
vkCmdBindPipeline(hCommandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pCS->m_hPipeline);
|
|
}
|
|
DECLARE_VULKAN_COMMAND(SetShaderData)
|
|
{
|
|
CVkMaterial *pMat = (CVkMaterial*)pShaderData;
|
|
CVkShader *pS = dynamic_cast<CVkShader*>(pMat->m_pShader);
|
|
CVkComputeShader *pCS = dynamic_cast<CVkComputeShader*>(pMat->m_pShader);
|
|
if (pS)
|
|
vkCmdBindDescriptorSets(hCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pS->m_hPipelineLayout, 0, pMat->m_hSets.GetSize(), pMat->m_hSets.GetData(), 0, 0 );
|
|
if (pCS)
|
|
vkCmdBindDescriptorSets(hCommandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pCS->m_hPipelineLayout, 0, pMat->m_hSets.GetSize(), pMat->m_hSets.GetData(), 0, 0 );
|
|
}
|
|
|
|
DECLARE_VULKAN_COMMAND(SetVertexBuffer)
|
|
{
|
|
CVkBuffer *pVkBuffer = (CVkBuffer*)pBuffer;
|
|
VkDeviceSize uOffset = 0;
|
|
vkCmdBindVertexBuffers(hCommandBuffer, uBinding, 1, &pVkBuffer->m_buffer, &uOffset);
|
|
}
|
|
|
|
DECLARE_VULKAN_COMMAND(DrawPrimitives)
|
|
{
|
|
vkCmdDraw(hCommandBuffer, nVertexCount, nInstanceCount, nFirstVertex, nFirstInstance);
|
|
}
|
|
|
|
DECLARE_VULKAN_COMMAND(SetScissors)
|
|
{
|
|
VkRect2D r = {
|
|
.offset = {
|
|
iX,
|
|
iY,
|
|
},
|
|
.extent = {
|
|
uWidth,
|
|
uHeight,
|
|
},
|
|
};
|
|
if (vkCmdSetScissorWithCount)
|
|
vkCmdSetScissorWithCount(hCommandBuffer, 1, &r);
|
|
else
|
|
vkCmdSetScissor(hCommandBuffer, 0, 1, &r);
|
|
}
|
|
|
|
DECLARE_VULKAN_COMMAND(SetViewport)
|
|
{
|
|
VkViewport v = {
|
|
fX,
|
|
fY+fHeight,
|
|
fWidth,
|
|
-fHeight,
|
|
fDepthMin,
|
|
fDepthMax
|
|
};
|
|
if (vkCmdSetScissorWithCount)
|
|
vkCmdSetViewportWithCount(hCommandBuffer, 1, &v);
|
|
else
|
|
vkCmdSetViewport(hCommandBuffer, 0, 1, &v);
|
|
}
|
|
DECLARE_VULKAN_COMMAND(ResolveImage)
|
|
{
|
|
CVkImage *pInput = (CVkImage*)VulkanGetObject(stInputImage, iCurrentFrame);
|
|
CVkImage *pOutput = (CVkImage*)VulkanGetObject(stOutputImage, iCurrentFrame);
|
|
VkImageResolve2 r = {
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2,
|
|
.srcSubresource = {
|
|
.aspectMask = pInput->m_range.aspectMask,
|
|
.layerCount = 1,
|
|
},
|
|
.srcOffset = {0,0,0},
|
|
.dstSubresource = {
|
|
.aspectMask = pOutput->m_range.aspectMask,
|
|
.layerCount = 1,
|
|
},
|
|
.dstOffset = {0,0,0},
|
|
.extent = {pInput->m_nWidth, pInput->m_nHeight, 1}
|
|
};
|
|
VkResolveImageInfo2 i = {
|
|
.sType = VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2,
|
|
.srcImage = pInput->m_image,
|
|
.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
|
.dstImage = pOutput->m_image,
|
|
.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
.regionCount = 1,
|
|
.pRegions = &r,
|
|
};
|
|
vkCmdResolveImage2(hCommandBuffer, &i);
|
|
}
|
|
|
|
static VkPipelineStageFlags2 GetStage( EStageHazard stage )
|
|
{
|
|
switch (stage)
|
|
{
|
|
case STAGE_HAZARD_COMPUTE:
|
|
return VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
|
|
case STAGE_HAZARD_TRANSFER:
|
|
return VK_PIPELINE_STAGE_2_TRANSFER_BIT;
|
|
case STAGE_HAZARD_RASTER_COLOR_OUT:
|
|
return VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
case STAGE_HAZARD_NONE:
|
|
return VK_PIPELINE_STAGE_2_NONE;
|
|
case STAGE_HAZARD_RASTER_EARLY_DEPTH_OUT:
|
|
return VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
|
|
case STAGE_HAZARD_RASTER_LATE_DEPTH_OUT:
|
|
return VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
|
|
}
|
|
|
|
}
|
|
static VkAccessFlags2 GetAccessSrc( uint32_t hazard, EStageHazard stage )
|
|
{
|
|
VkAccessFlags2 f = 0;
|
|
if (hazard & BARRIER_HAZARD_DRAW_ARGUMENTS)
|
|
f |= VK_ACCESS_2_SHADER_WRITE_BIT;
|
|
if (hazard & BARRIER_HAZARD_DESCRIPTOR)
|
|
f |= VK_ACCESS_2_SHADER_WRITE_BIT;
|
|
if (stage == STAGE_HAZARD_RASTER_EARLY_DEPTH_OUT)
|
|
{
|
|
if (hazard & BARRIER_HAZARD_DEPTH_STENCIL)
|
|
f |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
|
}
|
|
if (stage == STAGE_HAZARD_RASTER_COLOR_OUT)
|
|
{
|
|
if (hazard & BARRIER_HAZARD_RASTER_COLOR)
|
|
f |= VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT;
|
|
|
|
}
|
|
if (hazard == 0)
|
|
f |= VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT;
|
|
if (stage == STAGE_HAZARD_COMPUTE)
|
|
f |= VK_ACCESS_2_SHADER_STORAGE_READ_BIT | VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT;
|
|
return f;
|
|
|
|
}
|
|
static VkAccessFlags2 GetAccessDst( uint32_t hazard, EStageHazard stage )
|
|
{
|
|
VkAccessFlags2 f = 0;
|
|
if (hazard & BARRIER_HAZARD_DRAW_ARGUMENTS)
|
|
f |= VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT;
|
|
if (hazard & BARRIER_HAZARD_DESCRIPTOR)
|
|
f |= VK_ACCESS_2_SHADER_READ_BIT;
|
|
if (hazard & BARRIER_HAZARD_DEPTH_STENCIL)
|
|
f |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
|
if (hazard & BARRIER_HAZARD_RASTER_COLOR)
|
|
f |= VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
|
|
if (hazard == 0)
|
|
f |= VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT;
|
|
if (stage == STAGE_HAZARD_COMPUTE)
|
|
f |= VK_ACCESS_2_SHADER_STORAGE_READ_BIT | VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT;
|
|
return f;
|
|
}
|
|
static VkImageLayout GetLayout( EImageLayoutHazard hazard )
|
|
{
|
|
switch (hazard)
|
|
{
|
|
case IMAGE_LAYOUT_COLOR:
|
|
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
case IMAGE_LAYOUT_DEPTH_STENCIL:
|
|
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
case IMAGE_LAYOUT_GENERAL:
|
|
return VK_IMAGE_LAYOUT_GENERAL;
|
|
case IMAGE_LAYOUT_PRESENT:
|
|
return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
|
case IMAGE_LAYOUT_UNDEFINED:
|
|
return VK_IMAGE_LAYOUT_UNDEFINED;
|
|
case IMAGE_LAYOUT_TRANSFER_SRC:
|
|
return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
|
case IMAGE_LAYOUT_TRANSFER_DST:
|
|
return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
|
}
|
|
|
|
}
|
|
|
|
DECLARE_VULKAN_COMMAND(Barrier)
|
|
{
|
|
VkMemoryBarrier2 barrier = {};
|
|
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2;
|
|
barrier.srcStageMask = GetStage(eStageIn);
|
|
barrier.srcAccessMask = GetAccessSrc(eHazard, eStageIn);
|
|
barrier.dstStageMask = GetStage(eStageOut);
|
|
barrier.dstAccessMask = GetAccessDst(eHazard, eStageOut);
|
|
VkDependencyInfo dependency = {};
|
|
dependency.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
|
|
dependency.memoryBarrierCount = 1;
|
|
dependency.pMemoryBarriers = &barrier;
|
|
if (vkCmdPipelineBarrier2)
|
|
vkCmdPipelineBarrier2(hCommandBuffer, &dependency);
|
|
else if (vkCmdPipelineBarrier2KHR)
|
|
vkCmdPipelineBarrier2KHR(hCommandBuffer, &dependency);
|
|
else
|
|
{
|
|
VkMemoryBarrier barrier = {};
|
|
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
|
|
barrier.srcAccessMask = GetAccessSrc(eHazard, eStageIn);
|
|
barrier.dstAccessMask = GetAccessDst(eHazard, eStageOut);
|
|
vkCmdPipelineBarrier(hCommandBuffer,
|
|
GetStage(eStageIn),
|
|
GetStage(eStageOut),
|
|
0, 1,&barrier, 0, NULL, 0, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DECLARE_VULKAN_COMMAND(LayoutBarrier)
|
|
{
|
|
VkImageMemoryBarrier2 barrier = {};
|
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2;
|
|
barrier.srcStageMask = GetStage(eStageIn);
|
|
barrier.srcAccessMask = GetAccessSrc(eHazard, eStageIn);
|
|
barrier.dstStageMask = GetStage(eStageOut);
|
|
barrier.dstAccessMask = GetAccessDst(eHazard, eStageOut);
|
|
barrier.image = ((CVkImage*)pImage)->m_image;
|
|
barrier.subresourceRange = ((CVkImage*)pImage)->m_range;
|
|
barrier.oldLayout = GetLayout(eLayoutIn);
|
|
barrier.newLayout = GetLayout(eLayoutOut);
|
|
VkDependencyInfo dependency = {};
|
|
dependency.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
|
|
dependency.imageMemoryBarrierCount = 1;
|
|
dependency.pImageMemoryBarriers = &barrier;
|
|
if (vkCmdPipelineBarrier2)
|
|
vkCmdPipelineBarrier2(hCommandBuffer, &dependency);
|
|
else if (vkCmdPipelineBarrier2KHR)
|
|
vkCmdPipelineBarrier2KHR(hCommandBuffer, &dependency);
|
|
else
|
|
{
|
|
VkImageMemoryBarrier barrier = {};
|
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
barrier.srcAccessMask = GetAccessSrc(eHazard, eStageIn);
|
|
barrier.dstAccessMask = GetAccessDst(eHazard, eStageOut);
|
|
barrier.image = ((CVkImage*)pImage)->m_image;
|
|
barrier.subresourceRange = ((CVkImage*)pImage)->m_range;
|
|
barrier.oldLayout = GetLayout(eLayoutIn);
|
|
barrier.newLayout = GetLayout(eLayoutOut);
|
|
vkCmdPipelineBarrier(hCommandBuffer,
|
|
GetStage(eStageIn),
|
|
GetStage(eStageOut),
|
|
0, 0, NULL, 0, NULL, 1, &barrier);
|
|
|
|
}
|
|
}
|