2021-06-20 15:13:21 -04:00
|
|
|
#include "GSH_VulkanDrawMobile.h"
|
2021-09-18 11:56:54 -04:00
|
|
|
#include "GSH_VulkanDrawUtils.h"
|
2021-06-20 15:13:21 -04:00
|
|
|
#include "GSH_VulkanMemoryUtils.h"
|
|
|
|
#include "MemStream.h"
|
|
|
|
#include "vulkan/StructDefs.h"
|
|
|
|
#include "vulkan/Utils.h"
|
|
|
|
#include "nuanceur/Builder.h"
|
|
|
|
#include "nuanceur/generators/SpirvShaderGenerator.h"
|
|
|
|
#include "../GSHandler.h"
|
|
|
|
#include "../GsPixelFormats.h"
|
|
|
|
|
|
|
|
using namespace GSH_Vulkan;
|
|
|
|
|
|
|
|
#define VERTEX_ATTRIB_LOCATION_POSITION 0
|
|
|
|
#define VERTEX_ATTRIB_LOCATION_DEPTH 1
|
|
|
|
#define VERTEX_ATTRIB_LOCATION_COLOR 2
|
|
|
|
#define VERTEX_ATTRIB_LOCATION_TEXCOORD 3
|
|
|
|
#define VERTEX_ATTRIB_LOCATION_FOG 4
|
|
|
|
|
|
|
|
#define DESCRIPTOR_LOCATION_BUFFER_MEMORY 0
|
|
|
|
#define DESCRIPTOR_LOCATION_IMAGE_CLUT 1
|
|
|
|
#define DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_TEX 2
|
|
|
|
#define DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_FB 3
|
|
|
|
#define DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_DEPTH 4
|
2021-06-21 18:40:21 -04:00
|
|
|
#define DESCRIPTOR_LOCATION_IMAGE_INPUT_COLOR 5
|
2021-06-23 08:12:07 -04:00
|
|
|
#define DESCRIPTOR_LOCATION_IMAGE_INPUT_DEPTH 6
|
2021-06-20 15:13:21 -04:00
|
|
|
|
2021-06-23 08:12:07 -04:00
|
|
|
#define DRAW_AREA_SIZE 2048
|
2021-06-20 15:13:21 -04:00
|
|
|
#define MAX_VERTEX_COUNT 1024 * 512
|
|
|
|
|
|
|
|
#define DEPTH_MAX (4294967296.0f)
|
|
|
|
|
|
|
|
CDrawMobile::CDrawMobile(const ContextPtr& context, const FrameCommandBufferPtr& frameCommandBuffer)
|
2021-09-18 11:56:54 -04:00
|
|
|
: CDraw(context, frameCommandBuffer)
|
2021-07-19 12:59:36 -04:00
|
|
|
, m_loadPipelineCache(context->device)
|
|
|
|
, m_storePipelineCache(context->device)
|
2021-06-20 15:13:21 -04:00
|
|
|
{
|
|
|
|
CreateRenderPass();
|
2021-06-23 08:12:07 -04:00
|
|
|
CreateDrawImages();
|
2021-06-20 15:13:21 -04:00
|
|
|
CreateFramebuffer();
|
|
|
|
}
|
|
|
|
|
|
|
|
CDrawMobile::~CDrawMobile()
|
|
|
|
{
|
|
|
|
m_context->device.vkDestroyFramebuffer(m_context->device, m_framebuffer, nullptr);
|
|
|
|
m_context->device.vkDestroyRenderPass(m_context->device, m_renderPass, nullptr);
|
2021-06-23 08:12:07 -04:00
|
|
|
m_context->device.vkDestroyImageView(m_context->device, m_drawColorImageView, nullptr);
|
2021-06-20 15:13:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void CDrawMobile::SetPipelineCaps(const PIPELINE_CAPS& caps)
|
|
|
|
{
|
|
|
|
bool changed = static_cast<uint64>(caps) != static_cast<uint64>(m_pipelineCaps);
|
|
|
|
if(!changed) return;
|
2021-07-27 10:56:13 -04:00
|
|
|
auto prevLoadStoreCaps = MakeLoadStorePipelineCaps(m_pipelineCaps);
|
|
|
|
auto nextLoadStoreCaps = MakeLoadStorePipelineCaps(caps);
|
|
|
|
if(static_cast<uint64>(prevLoadStoreCaps) != static_cast<uint64>(nextLoadStoreCaps))
|
2021-06-20 15:13:21 -04:00
|
|
|
{
|
|
|
|
FlushRenderPass();
|
|
|
|
}
|
2021-08-28 19:15:46 -04:00
|
|
|
if(caps.textureUseMemoryCopy)
|
|
|
|
{
|
|
|
|
FlushRenderPass();
|
|
|
|
}
|
2021-06-20 15:13:21 -04:00
|
|
|
FlushVertices();
|
|
|
|
m_pipelineCaps = caps;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDrawMobile::SetFramebufferParams(uint32 addr, uint32 width, uint32 writeMask)
|
|
|
|
{
|
2021-09-02 13:05:01 -04:00
|
|
|
bool storeChanged =
|
2021-09-18 11:56:54 -04:00
|
|
|
(m_pushConstants.fbBufAddr != addr) ||
|
|
|
|
(m_pushConstants.fbBufWidth != width);
|
2021-09-02 13:05:01 -04:00
|
|
|
bool drawChanged =
|
2021-09-18 11:56:54 -04:00
|
|
|
(m_pushConstants.fbWriteMask != writeMask);
|
2021-09-02 13:05:01 -04:00
|
|
|
if(!storeChanged && !drawChanged) return;
|
|
|
|
if(storeChanged)
|
|
|
|
{
|
|
|
|
FlushRenderPass();
|
|
|
|
}
|
|
|
|
if(drawChanged)
|
|
|
|
{
|
|
|
|
FlushVertices();
|
|
|
|
}
|
2021-09-18 11:56:54 -04:00
|
|
|
m_pushConstants.fbBufAddr = addr;
|
|
|
|
m_pushConstants.fbBufWidth = width;
|
|
|
|
m_pushConstants.fbWriteMask = writeMask;
|
2021-06-20 15:13:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void CDrawMobile::SetDepthbufferParams(uint32 addr, uint32 width)
|
|
|
|
{
|
|
|
|
bool changed =
|
2021-09-18 11:56:54 -04:00
|
|
|
(m_pushConstants.depthBufAddr != addr) ||
|
|
|
|
(m_pushConstants.depthBufWidth != width);
|
2021-06-20 15:13:21 -04:00
|
|
|
if(!changed) return;
|
2021-06-22 10:47:01 -04:00
|
|
|
FlushRenderPass();
|
2021-09-18 11:56:54 -04:00
|
|
|
m_pushConstants.depthBufAddr = addr;
|
|
|
|
m_pushConstants.depthBufWidth = width;
|
2021-06-20 15:13:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void CDrawMobile::SetScissor(uint32 scissorX, uint32 scissorY, uint32 scissorWidth, uint32 scissorHeight)
|
|
|
|
{
|
|
|
|
bool changed =
|
|
|
|
(m_scissorX != scissorX) ||
|
|
|
|
(m_scissorY != scissorY) ||
|
|
|
|
(m_scissorWidth != scissorWidth) ||
|
|
|
|
(m_scissorHeight != scissorHeight);
|
|
|
|
if(!changed) return;
|
2021-08-23 13:13:07 -04:00
|
|
|
FlushRenderPass();
|
2021-06-20 15:13:21 -04:00
|
|
|
m_scissorX = scissorX;
|
|
|
|
m_scissorY = scissorY;
|
|
|
|
m_scissorWidth = scissorWidth;
|
|
|
|
m_scissorHeight = scissorHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDrawMobile::FlushVertices()
|
|
|
|
{
|
|
|
|
uint32 vertexCount = m_passVertexEnd - m_passVertexStart;
|
|
|
|
if(vertexCount == 0) return;
|
|
|
|
|
|
|
|
auto& frame = m_frames[m_frameCommandBuffer->GetCurrentFrame()];
|
|
|
|
auto commandBuffer = m_frameCommandBuffer->GetCommandBuffer();
|
|
|
|
|
2021-08-26 13:07:22 -04:00
|
|
|
for(auto vertex = frame.vertexBufferPtr + m_passVertexStart; vertex != frame.vertexBufferPtr + m_passVertexEnd; vertex++)
|
|
|
|
{
|
|
|
|
m_renderPassMinX = std::min(vertex->x, m_renderPassMinX);
|
|
|
|
m_renderPassMinY = std::min(vertex->y, m_renderPassMinY);
|
|
|
|
m_renderPassMaxX = std::max(vertex->x, m_renderPassMaxX);
|
|
|
|
m_renderPassMaxY = std::max(vertex->y, m_renderPassMaxY);
|
|
|
|
}
|
|
|
|
|
2021-08-28 19:15:46 -04:00
|
|
|
if(m_pipelineCaps.textureUseMemoryCopy)
|
|
|
|
{
|
|
|
|
assert(!m_renderPassBegun);
|
|
|
|
m_memoryCopyRegion.Reset();
|
|
|
|
}
|
2021-09-10 16:06:20 -04:00
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
{
|
|
|
|
VkViewport viewport = {};
|
|
|
|
viewport.width = DRAW_AREA_SIZE;
|
|
|
|
viewport.height = DRAW_AREA_SIZE;
|
|
|
|
viewport.maxDepth = 1.0f;
|
|
|
|
m_context->device.vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
|
|
|
|
|
|
|
|
VkRect2D scissor = {};
|
|
|
|
scissor.offset.x = m_scissorX;
|
|
|
|
scissor.offset.y = m_scissorY;
|
|
|
|
scissor.extent.width = m_scissorWidth;
|
|
|
|
scissor.extent.height = m_scissorHeight;
|
|
|
|
m_context->device.vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!m_renderPassBegun)
|
|
|
|
{
|
|
|
|
auto renderPassBeginInfo = Framework::Vulkan::RenderPassBeginInfo();
|
|
|
|
renderPassBeginInfo.renderPass = m_renderPass;
|
|
|
|
renderPassBeginInfo.renderArea.extent.width = DRAW_AREA_SIZE;
|
|
|
|
renderPassBeginInfo.renderArea.extent.height = DRAW_AREA_SIZE;
|
|
|
|
renderPassBeginInfo.framebuffer = m_framebuffer;
|
|
|
|
m_context->device.vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
|
|
|
|
2021-06-22 14:04:39 -04:00
|
|
|
//Load from memory
|
2021-07-19 12:59:36 -04:00
|
|
|
|
|
|
|
//Find pipeline and create it if we've never encountered it before
|
2021-07-27 10:56:13 -04:00
|
|
|
auto strippedCaps = MakeLoadStorePipelineCaps(m_pipelineCaps);
|
2021-07-19 12:59:36 -04:00
|
|
|
auto loadPipeline = m_loadPipelineCache.TryGetPipeline(strippedCaps);
|
|
|
|
if(!loadPipeline)
|
|
|
|
{
|
|
|
|
loadPipeline = m_loadPipelineCache.RegisterPipeline(strippedCaps, CreateLoadPipeline(strippedCaps));
|
|
|
|
}
|
|
|
|
|
2021-06-22 14:04:39 -04:00
|
|
|
auto descriptorSetCaps = make_convertible<DESCRIPTORSET_CAPS>(0);
|
2021-07-19 12:59:36 -04:00
|
|
|
descriptorSetCaps.framebufferFormat = m_pipelineCaps.framebufferFormat;
|
|
|
|
descriptorSetCaps.depthbufferFormat = m_pipelineCaps.depthbufferFormat;
|
2021-06-22 14:04:39 -04:00
|
|
|
|
2021-07-19 12:59:36 -04:00
|
|
|
auto descriptorSet = PrepareDescriptorSet(loadPipeline->descriptorSetLayout, descriptorSetCaps);
|
2021-06-22 14:04:39 -04:00
|
|
|
|
2021-07-19 12:59:36 -04:00
|
|
|
m_context->device.vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, loadPipeline->pipelineLayout,
|
2021-06-22 14:04:39 -04:00
|
|
|
0, 1, &descriptorSet, 0, nullptr);
|
2021-07-19 12:59:36 -04:00
|
|
|
m_context->device.vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, loadPipeline->pipeline);
|
|
|
|
m_context->device.vkCmdPushConstants(commandBuffer, loadPipeline->pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT,
|
2021-09-18 11:56:54 -04:00
|
|
|
0, sizeof(DRAW_PIPELINE_PUSHCONSTANTS), &m_pushConstants);
|
2021-06-22 14:04:39 -04:00
|
|
|
m_context->device.vkCmdDraw(commandBuffer, 3, 1, 0, 0);
|
2021-06-21 17:33:19 -04:00
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
m_context->device.vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE);
|
2021-06-21 17:33:19 -04:00
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
m_renderPassBegun = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Find pipeline and create it if we've never encountered it before
|
2021-09-18 11:56:54 -04:00
|
|
|
auto drawPipeline = m_pipelineCache.TryGetPipeline(m_pipelineCaps);
|
2021-06-20 15:13:21 -04:00
|
|
|
if(!drawPipeline)
|
|
|
|
{
|
2021-09-18 11:56:54 -04:00
|
|
|
drawPipeline = m_pipelineCache.RegisterPipeline(m_pipelineCaps, CreateDrawPipeline(m_pipelineCaps));
|
2021-06-20 15:13:21 -04:00
|
|
|
}
|
|
|
|
|
2021-09-03 11:57:02 -04:00
|
|
|
{
|
|
|
|
auto memoryBarrier = Framework::Vulkan::MemoryBarrier();
|
|
|
|
memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
|
|
memoryBarrier.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
|
|
|
|
|
|
|
|
m_context->device.vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
2021-09-10 16:06:20 -04:00
|
|
|
VK_DEPENDENCY_BY_REGION_BIT, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
|
2021-09-03 11:57:02 -04:00
|
|
|
}
|
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
auto descriptorSetCaps = make_convertible<DESCRIPTORSET_CAPS>(0);
|
|
|
|
descriptorSetCaps.hasTexture = m_pipelineCaps.hasTexture;
|
|
|
|
descriptorSetCaps.framebufferFormat = m_pipelineCaps.framebufferFormat;
|
|
|
|
descriptorSetCaps.depthbufferFormat = m_pipelineCaps.depthbufferFormat;
|
|
|
|
descriptorSetCaps.textureFormat = m_pipelineCaps.textureFormat;
|
|
|
|
|
|
|
|
auto descriptorSet = PrepareDescriptorSet(drawPipeline->descriptorSetLayout, descriptorSetCaps);
|
|
|
|
|
|
|
|
std::vector<uint32> descriptorDynamicOffsets;
|
|
|
|
|
|
|
|
if(m_pipelineCaps.hasTexture && CGsPixelFormats::IsPsmIDTEX(m_pipelineCaps.textureFormat))
|
|
|
|
{
|
|
|
|
descriptorDynamicOffsets.push_back(m_clutBufferOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_context->device.vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, drawPipeline->pipelineLayout,
|
|
|
|
0, 1, &descriptorSet, static_cast<uint32_t>(descriptorDynamicOffsets.size()), descriptorDynamicOffsets.data());
|
|
|
|
|
|
|
|
m_context->device.vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, drawPipeline->pipeline);
|
|
|
|
|
|
|
|
VkDeviceSize vertexBufferOffset = (m_passVertexStart * sizeof(PRIM_VERTEX));
|
|
|
|
VkBuffer vertexBuffer = frame.vertexBuffer;
|
|
|
|
m_context->device.vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
|
|
|
|
|
|
|
|
m_context->device.vkCmdPushConstants(commandBuffer, drawPipeline->pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT,
|
2021-09-18 11:56:54 -04:00
|
|
|
0, sizeof(DRAW_PIPELINE_PUSHCONSTANTS), &m_pushConstants);
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
m_context->device.vkCmdDraw(commandBuffer, vertexCount, 1, 0, 0);
|
|
|
|
|
|
|
|
m_passVertexStart = m_passVertexEnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDrawMobile::FlushRenderPass()
|
|
|
|
{
|
|
|
|
FlushVertices();
|
|
|
|
if(m_renderPassBegun)
|
|
|
|
{
|
|
|
|
auto commandBuffer = m_frameCommandBuffer->GetCommandBuffer();
|
|
|
|
m_context->device.vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE);
|
2021-06-21 17:33:19 -04:00
|
|
|
|
|
|
|
//Store to memory
|
2021-07-19 12:59:36 -04:00
|
|
|
|
2021-08-26 13:07:22 -04:00
|
|
|
int32 clippedX0 = std::clamp<int32>(m_renderPassMinX, m_scissorX, m_scissorX + m_scissorWidth);
|
|
|
|
int32 clippedX1 = std::clamp<int32>(m_renderPassMaxX, m_scissorX, m_scissorX + m_scissorWidth);
|
|
|
|
int32 clippedY0 = std::clamp<int32>(m_renderPassMinY, m_scissorY, m_scissorY + m_scissorHeight);
|
|
|
|
int32 clippedY1 = std::clamp<int32>(m_renderPassMaxY, m_scissorY, m_scissorY + m_scissorHeight);
|
2021-09-10 16:06:20 -04:00
|
|
|
|
2021-08-26 13:07:22 -04:00
|
|
|
VkRect2D scissor = {};
|
|
|
|
scissor.offset.x = clippedX0;
|
|
|
|
scissor.offset.y = clippedY0;
|
|
|
|
scissor.extent.width = clippedX1 - clippedX0;
|
|
|
|
scissor.extent.height = clippedY1 - clippedY0;
|
|
|
|
m_context->device.vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
|
|
|
|
2021-07-19 12:59:36 -04:00
|
|
|
//Find pipeline and create it if we've never encountered it before
|
2021-07-27 10:56:13 -04:00
|
|
|
auto strippedCaps = MakeLoadStorePipelineCaps(m_pipelineCaps);
|
2021-07-19 12:59:36 -04:00
|
|
|
auto storePipeline = m_storePipelineCache.TryGetPipeline(strippedCaps);
|
|
|
|
if(!storePipeline)
|
|
|
|
{
|
|
|
|
storePipeline = m_storePipelineCache.RegisterPipeline(strippedCaps, CreateStorePipeline(strippedCaps));
|
|
|
|
}
|
|
|
|
|
2021-06-21 17:33:19 -04:00
|
|
|
auto descriptorSetCaps = make_convertible<DESCRIPTORSET_CAPS>(0);
|
2021-07-19 12:59:36 -04:00
|
|
|
descriptorSetCaps.framebufferFormat = m_pipelineCaps.framebufferFormat;
|
|
|
|
descriptorSetCaps.depthbufferFormat = m_pipelineCaps.depthbufferFormat;
|
2021-06-21 17:33:19 -04:00
|
|
|
|
2021-07-19 12:59:36 -04:00
|
|
|
auto descriptorSet = PrepareDescriptorSet(storePipeline->descriptorSetLayout, descriptorSetCaps);
|
2021-06-21 17:33:19 -04:00
|
|
|
|
2021-07-19 12:59:36 -04:00
|
|
|
m_context->device.vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, storePipeline->pipelineLayout,
|
2021-06-21 17:33:19 -04:00
|
|
|
0, 1, &descriptorSet, 0, nullptr);
|
2021-07-19 12:59:36 -04:00
|
|
|
m_context->device.vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, storePipeline->pipeline);
|
|
|
|
m_context->device.vkCmdPushConstants(commandBuffer, storePipeline->pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT,
|
2021-09-18 11:56:54 -04:00
|
|
|
0, sizeof(DRAW_PIPELINE_PUSHCONSTANTS), &m_pushConstants);
|
2021-06-21 17:33:19 -04:00
|
|
|
m_context->device.vkCmdDraw(commandBuffer, 3, 1, 0, 0);
|
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
m_context->device.vkCmdEndRenderPass(commandBuffer);
|
|
|
|
m_renderPassBegun = false;
|
|
|
|
}
|
2021-08-26 13:07:22 -04:00
|
|
|
m_renderPassMinX = FLT_MAX;
|
|
|
|
m_renderPassMinY = FLT_MAX;
|
|
|
|
m_renderPassMaxX = -FLT_MAX;
|
|
|
|
m_renderPassMaxY = -FLT_MAX;
|
2021-06-20 15:13:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
VkDescriptorSet CDrawMobile::PrepareDescriptorSet(VkDescriptorSetLayout descriptorSetLayout, const DESCRIPTORSET_CAPS& caps)
|
|
|
|
{
|
2021-09-18 11:56:54 -04:00
|
|
|
auto descriptorSetIterator = m_descriptorSetCache.find(caps);
|
|
|
|
if(descriptorSetIterator != std::end(m_descriptorSetCache))
|
2021-06-20 15:13:21 -04:00
|
|
|
{
|
|
|
|
return descriptorSetIterator->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto result = VK_SUCCESS;
|
|
|
|
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
|
|
|
|
|
|
|
|
//Allocate descriptor set
|
|
|
|
{
|
|
|
|
auto setAllocateInfo = Framework::Vulkan::DescriptorSetAllocateInfo();
|
|
|
|
setAllocateInfo.descriptorPool = m_context->descriptorPool;
|
|
|
|
setAllocateInfo.descriptorSetCount = 1;
|
|
|
|
setAllocateInfo.pSetLayouts = &descriptorSetLayout;
|
|
|
|
|
|
|
|
result = m_context->device.vkAllocateDescriptorSets(m_context->device, &setAllocateInfo, &descriptorSet);
|
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Update descriptor set
|
|
|
|
{
|
|
|
|
VkDescriptorBufferInfo descriptorMemoryBufferInfo = {};
|
|
|
|
descriptorMemoryBufferInfo.buffer = m_context->memoryBuffer;
|
|
|
|
descriptorMemoryBufferInfo.range = VK_WHOLE_SIZE;
|
|
|
|
|
|
|
|
VkDescriptorBufferInfo descriptorClutBufferInfo = {};
|
|
|
|
descriptorClutBufferInfo.buffer = m_context->clutBuffer;
|
|
|
|
descriptorClutBufferInfo.range = VK_WHOLE_SIZE;
|
|
|
|
|
|
|
|
VkDescriptorImageInfo descriptorTexSwizzleTableImageInfo = {};
|
|
|
|
descriptorTexSwizzleTableImageInfo.imageView = m_context->GetSwizzleTable(caps.textureFormat);
|
|
|
|
descriptorTexSwizzleTableImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
|
|
|
|
|
|
|
VkDescriptorImageInfo descriptorFbSwizzleTableImageInfo = {};
|
|
|
|
descriptorFbSwizzleTableImageInfo.imageView = m_context->GetSwizzleTable(caps.framebufferFormat);
|
|
|
|
descriptorFbSwizzleTableImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
|
|
|
|
|
|
|
VkDescriptorImageInfo descriptorDepthSwizzleTableImageInfo = {};
|
|
|
|
descriptorDepthSwizzleTableImageInfo.imageView = m_context->GetSwizzleTable(caps.depthbufferFormat);
|
|
|
|
descriptorDepthSwizzleTableImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
|
|
|
|
2021-06-21 18:40:21 -04:00
|
|
|
VkDescriptorImageInfo descriptorInputColorImageInfo = {};
|
|
|
|
descriptorInputColorImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
2021-06-23 08:12:07 -04:00
|
|
|
descriptorInputColorImageInfo.imageView = m_drawColorImageView;
|
|
|
|
|
|
|
|
VkDescriptorImageInfo descriptorInputDepthImageInfo = {};
|
|
|
|
descriptorInputDepthImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
|
|
|
descriptorInputDepthImageInfo.imageView = m_drawDepthImageView;
|
2021-06-21 18:40:21 -04:00
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
std::vector<VkWriteDescriptorSet> writes;
|
|
|
|
|
|
|
|
{
|
|
|
|
auto writeSet = Framework::Vulkan::WriteDescriptorSet();
|
|
|
|
writeSet.dstSet = descriptorSet;
|
|
|
|
writeSet.dstBinding = DESCRIPTOR_LOCATION_BUFFER_MEMORY;
|
|
|
|
writeSet.descriptorCount = 1;
|
|
|
|
writeSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
|
|
writeSet.pBufferInfo = &descriptorMemoryBufferInfo;
|
|
|
|
writes.push_back(writeSet);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto writeSet = Framework::Vulkan::WriteDescriptorSet();
|
|
|
|
writeSet.dstSet = descriptorSet;
|
|
|
|
writeSet.dstBinding = DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_FB;
|
|
|
|
writeSet.descriptorCount = 1;
|
|
|
|
writeSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
writeSet.pImageInfo = &descriptorFbSwizzleTableImageInfo;
|
|
|
|
writes.push_back(writeSet);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto writeSet = Framework::Vulkan::WriteDescriptorSet();
|
|
|
|
writeSet.dstSet = descriptorSet;
|
|
|
|
writeSet.dstBinding = DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_DEPTH;
|
|
|
|
writeSet.descriptorCount = 1;
|
|
|
|
writeSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
writeSet.pImageInfo = &descriptorDepthSwizzleTableImageInfo;
|
|
|
|
writes.push_back(writeSet);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(caps.hasTexture)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto writeSet = Framework::Vulkan::WriteDescriptorSet();
|
|
|
|
writeSet.dstSet = descriptorSet;
|
|
|
|
writeSet.dstBinding = DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_TEX;
|
|
|
|
writeSet.descriptorCount = 1;
|
|
|
|
writeSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
writeSet.pImageInfo = &descriptorTexSwizzleTableImageInfo;
|
|
|
|
writes.push_back(writeSet);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(CGsPixelFormats::IsPsmIDTEX(caps.textureFormat))
|
|
|
|
{
|
|
|
|
auto writeSet = Framework::Vulkan::WriteDescriptorSet();
|
|
|
|
writeSet.dstSet = descriptorSet;
|
|
|
|
writeSet.dstBinding = DESCRIPTOR_LOCATION_IMAGE_CLUT;
|
|
|
|
writeSet.descriptorCount = 1;
|
|
|
|
writeSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
|
|
|
|
writeSet.pBufferInfo = &descriptorClutBufferInfo;
|
|
|
|
writes.push_back(writeSet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-21 18:40:21 -04:00
|
|
|
{
|
|
|
|
auto writeSet = Framework::Vulkan::WriteDescriptorSet();
|
|
|
|
writeSet.dstSet = descriptorSet;
|
|
|
|
writeSet.dstBinding = DESCRIPTOR_LOCATION_IMAGE_INPUT_COLOR;
|
|
|
|
writeSet.descriptorCount = 1;
|
|
|
|
writeSet.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
|
|
|
writeSet.pImageInfo = &descriptorInputColorImageInfo;
|
|
|
|
writes.push_back(writeSet);
|
|
|
|
}
|
|
|
|
|
2021-06-23 08:12:07 -04:00
|
|
|
{
|
|
|
|
auto writeSet = Framework::Vulkan::WriteDescriptorSet();
|
|
|
|
writeSet.dstSet = descriptorSet;
|
|
|
|
writeSet.dstBinding = DESCRIPTOR_LOCATION_IMAGE_INPUT_DEPTH;
|
|
|
|
writeSet.descriptorCount = 1;
|
|
|
|
writeSet.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
|
|
|
writeSet.pImageInfo = &descriptorInputDepthImageInfo;
|
|
|
|
writes.push_back(writeSet);
|
|
|
|
}
|
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
m_context->device.vkUpdateDescriptorSets(m_context->device, static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
|
|
|
}
|
|
|
|
|
2021-09-18 11:56:54 -04:00
|
|
|
m_descriptorSetCache.insert(std::make_pair(caps, descriptorSet));
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
return descriptorSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDrawMobile::CreateFramebuffer()
|
|
|
|
{
|
|
|
|
assert(m_renderPass != VK_NULL_HANDLE);
|
|
|
|
assert(m_framebuffer == VK_NULL_HANDLE);
|
|
|
|
|
2021-06-23 08:12:07 -04:00
|
|
|
std::vector<VkImageView> attachments;
|
|
|
|
attachments.push_back(m_drawColorImageView);
|
|
|
|
attachments.push_back(m_drawDepthImageView);
|
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
auto frameBufferCreateInfo = Framework::Vulkan::FramebufferCreateInfo();
|
|
|
|
frameBufferCreateInfo.renderPass = m_renderPass;
|
|
|
|
frameBufferCreateInfo.width = DRAW_AREA_SIZE;
|
|
|
|
frameBufferCreateInfo.height = DRAW_AREA_SIZE;
|
|
|
|
frameBufferCreateInfo.layers = 1;
|
2021-06-23 08:12:07 -04:00
|
|
|
frameBufferCreateInfo.attachmentCount = attachments.size();
|
|
|
|
frameBufferCreateInfo.pAttachments = attachments.data();
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
auto result = m_context->device.vkCreateFramebuffer(m_context->device, &frameBufferCreateInfo, nullptr, &m_framebuffer);
|
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDrawMobile::CreateRenderPass()
|
|
|
|
{
|
|
|
|
assert(m_renderPass == VK_NULL_HANDLE);
|
|
|
|
|
|
|
|
auto result = VK_SUCCESS;
|
|
|
|
|
|
|
|
VkAttachmentReference colorRef = {};
|
|
|
|
colorRef.attachment = 0;
|
2021-06-21 10:49:30 -04:00
|
|
|
colorRef.layout = VK_IMAGE_LAYOUT_GENERAL;
|
2021-06-20 15:13:21 -04:00
|
|
|
|
2021-06-23 08:12:07 -04:00
|
|
|
VkAttachmentReference depthRef = {};
|
|
|
|
depthRef.attachment = 1;
|
|
|
|
depthRef.layout = VK_IMAGE_LAYOUT_GENERAL;
|
|
|
|
|
2021-07-13 09:08:19 -04:00
|
|
|
std::vector<VkAttachmentReference> attachmentRefs;
|
|
|
|
attachmentRefs.push_back(colorRef);
|
|
|
|
attachmentRefs.push_back(depthRef);
|
2021-06-23 08:12:07 -04:00
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
std::vector<VkSubpassDescription> subpasses;
|
2021-06-21 17:33:19 -04:00
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
//Unswizzle Subpass
|
|
|
|
{
|
|
|
|
VkSubpassDescription subpass = {};
|
|
|
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
2021-07-13 09:08:19 -04:00
|
|
|
subpass.pColorAttachments = attachmentRefs.data();
|
|
|
|
subpass.colorAttachmentCount = attachmentRefs.size();
|
2021-06-20 15:13:21 -04:00
|
|
|
subpasses.push_back(subpass);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Draw Subpass
|
|
|
|
{
|
|
|
|
VkSubpassDescription subpass = {};
|
|
|
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
2021-07-13 09:08:19 -04:00
|
|
|
subpass.pColorAttachments = attachmentRefs.data();
|
|
|
|
subpass.colorAttachmentCount = attachmentRefs.size();
|
|
|
|
subpass.pInputAttachments = attachmentRefs.data();
|
|
|
|
subpass.inputAttachmentCount = attachmentRefs.size();
|
2021-06-20 15:13:21 -04:00
|
|
|
subpasses.push_back(subpass);
|
|
|
|
}
|
2021-06-21 17:33:19 -04:00
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
//Swizzle pass
|
|
|
|
{
|
|
|
|
VkSubpassDescription subpass = {};
|
|
|
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
2021-07-13 09:08:19 -04:00
|
|
|
subpass.pColorAttachments = attachmentRefs.data();
|
|
|
|
subpass.colorAttachmentCount = attachmentRefs.size();
|
|
|
|
subpass.pInputAttachments = attachmentRefs.data();
|
|
|
|
subpass.inputAttachmentCount = attachmentRefs.size();
|
2021-06-20 15:13:21 -04:00
|
|
|
subpasses.push_back(subpass);
|
|
|
|
}
|
|
|
|
|
2021-06-21 10:49:30 -04:00
|
|
|
std::vector<VkSubpassDependency> subpassDependencies;
|
|
|
|
|
2021-09-09 13:13:56 -04:00
|
|
|
{
|
|
|
|
VkSubpassDependency subpassDependency = {};
|
|
|
|
subpassDependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
|
|
|
subpassDependency.srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
|
|
subpassDependency.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
|
|
|
|
subpassDependency.dstSubpass = 0;
|
|
|
|
subpassDependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
|
|
subpassDependency.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
2021-09-28 11:35:49 -04:00
|
|
|
subpassDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
2021-09-09 13:13:56 -04:00
|
|
|
|
|
|
|
subpassDependencies.push_back(subpassDependency);
|
|
|
|
}
|
|
|
|
|
2021-06-21 10:49:30 -04:00
|
|
|
{
|
|
|
|
VkSubpassDependency subpassDependency = {};
|
|
|
|
subpassDependency.srcSubpass = 0;
|
|
|
|
subpassDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
|
|
subpassDependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
|
|
subpassDependency.dstSubpass = 1;
|
|
|
|
subpassDependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
|
|
subpassDependency.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
|
2021-09-28 11:35:49 -04:00
|
|
|
subpassDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
2021-06-21 10:49:30 -04:00
|
|
|
|
|
|
|
subpassDependencies.push_back(subpassDependency);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkSubpassDependency subpassDependency = {};
|
|
|
|
subpassDependency.srcSubpass = 1;
|
|
|
|
subpassDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
|
|
subpassDependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
|
|
subpassDependency.dstSubpass = 1;
|
|
|
|
subpassDependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
|
|
subpassDependency.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
|
|
|
|
subpassDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
|
|
|
|
|
|
|
subpassDependencies.push_back(subpassDependency);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkSubpassDependency subpassDependency = {};
|
|
|
|
subpassDependency.srcSubpass = 1;
|
|
|
|
subpassDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
|
|
subpassDependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
|
|
subpassDependency.dstSubpass = 2;
|
|
|
|
subpassDependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
|
|
subpassDependency.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
|
2021-09-28 11:35:49 -04:00
|
|
|
subpassDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
2021-06-21 10:49:30 -04:00
|
|
|
|
|
|
|
subpassDependencies.push_back(subpassDependency);
|
|
|
|
}
|
2021-06-20 15:13:21 -04:00
|
|
|
|
2021-09-09 13:13:56 -04:00
|
|
|
{
|
|
|
|
VkSubpassDependency subpassDependency = {};
|
|
|
|
subpassDependency.srcSubpass = 2;
|
|
|
|
subpassDependency.srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
|
|
subpassDependency.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
|
|
|
|
subpassDependency.dstSubpass = VK_SUBPASS_EXTERNAL;
|
|
|
|
subpassDependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
|
|
|
subpassDependency.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
2021-09-28 11:35:49 -04:00
|
|
|
subpassDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
2021-09-09 13:13:56 -04:00
|
|
|
|
|
|
|
subpassDependencies.push_back(subpassDependency);
|
|
|
|
}
|
|
|
|
|
2021-06-23 08:12:07 -04:00
|
|
|
std::vector<VkAttachmentDescription> attachments;
|
|
|
|
|
|
|
|
{
|
|
|
|
VkAttachmentDescription attachment = {};
|
2021-08-15 14:22:45 -04:00
|
|
|
attachment.format = VK_FORMAT_R32_UINT;
|
2021-06-23 08:12:07 -04:00
|
|
|
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
|
|
attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
|
|
attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
attachments.push_back(attachment);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkAttachmentDescription attachment = {};
|
2021-07-13 09:08:19 -04:00
|
|
|
attachment.format = VK_FORMAT_R32_UINT;
|
2021-06-23 08:12:07 -04:00
|
|
|
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
|
|
attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
2021-07-13 09:08:19 -04:00
|
|
|
attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
2021-06-23 08:12:07 -04:00
|
|
|
attachments.push_back(attachment);
|
|
|
|
}
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
auto renderPassCreateInfo = Framework::Vulkan::RenderPassCreateInfo();
|
|
|
|
renderPassCreateInfo.subpassCount = subpasses.size();
|
|
|
|
renderPassCreateInfo.pSubpasses = subpasses.data();
|
2021-06-23 08:12:07 -04:00
|
|
|
renderPassCreateInfo.attachmentCount = attachments.size();
|
|
|
|
renderPassCreateInfo.pAttachments = attachments.data();
|
2021-06-21 10:49:30 -04:00
|
|
|
renderPassCreateInfo.dependencyCount = subpassDependencies.size();
|
|
|
|
renderPassCreateInfo.pDependencies = subpassDependencies.data();
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
result = m_context->device.vkCreateRenderPass(m_context->device, &renderPassCreateInfo, nullptr, &m_renderPass);
|
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
PIPELINE CDrawMobile::CreateDrawPipeline(const PIPELINE_CAPS& caps)
|
|
|
|
{
|
|
|
|
PIPELINE drawPipeline;
|
|
|
|
|
2021-09-18 11:56:54 -04:00
|
|
|
auto vertexShader = CreateVertexShader(caps);
|
2021-06-20 15:13:21 -04:00
|
|
|
auto fragmentShader = CreateDrawFragmentShader(caps);
|
|
|
|
|
|
|
|
auto result = VK_SUCCESS;
|
|
|
|
|
|
|
|
{
|
|
|
|
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings;
|
|
|
|
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_BUFFER_MEMORY;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_FB;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_DEPTH;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(caps.hasTexture)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_TEX;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(CGsPixelFormats::IsPsmIDTEX(caps.textureFormat))
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_CLUT;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-21 18:40:21 -04:00
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_INPUT_COLOR;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
2021-06-23 08:12:07 -04:00
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_INPUT_DEPTH;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
auto setLayoutCreateInfo = Framework::Vulkan::DescriptorSetLayoutCreateInfo();
|
|
|
|
setLayoutCreateInfo.bindingCount = static_cast<uint32>(setLayoutBindings.size());
|
|
|
|
setLayoutCreateInfo.pBindings = setLayoutBindings.data();
|
|
|
|
|
|
|
|
result = m_context->device.vkCreateDescriptorSetLayout(m_context->device, &setLayoutCreateInfo, nullptr, &drawPipeline.descriptorSetLayout);
|
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkPushConstantRange pushConstantInfo = {};
|
|
|
|
pushConstantInfo.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
pushConstantInfo.offset = 0;
|
|
|
|
pushConstantInfo.size = sizeof(DRAW_PIPELINE_PUSHCONSTANTS);
|
|
|
|
|
|
|
|
auto pipelineLayoutCreateInfo = Framework::Vulkan::PipelineLayoutCreateInfo();
|
|
|
|
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
|
|
|
|
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantInfo;
|
|
|
|
pipelineLayoutCreateInfo.setLayoutCount = 1;
|
|
|
|
pipelineLayoutCreateInfo.pSetLayouts = &drawPipeline.descriptorSetLayout;
|
|
|
|
|
|
|
|
result = m_context->device.vkCreatePipelineLayout(m_context->device, &pipelineLayoutCreateInfo, nullptr, &drawPipeline.pipelineLayout);
|
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto inputAssemblyInfo = Framework::Vulkan::PipelineInputAssemblyStateCreateInfo();
|
|
|
|
switch(caps.primitiveType)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
case PIPELINE_PRIMITIVE_TRIANGLE:
|
|
|
|
inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
|
|
|
break;
|
|
|
|
case PIPELINE_PRIMITIVE_LINE:
|
|
|
|
inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<VkVertexInputAttributeDescription> vertexAttributes;
|
|
|
|
|
|
|
|
{
|
|
|
|
VkVertexInputAttributeDescription vertexAttributeDesc = {};
|
|
|
|
vertexAttributeDesc.format = VK_FORMAT_R32G32_SFLOAT;
|
|
|
|
vertexAttributeDesc.offset = offsetof(PRIM_VERTEX, x);
|
|
|
|
vertexAttributeDesc.location = VERTEX_ATTRIB_LOCATION_POSITION;
|
|
|
|
vertexAttributes.push_back(vertexAttributeDesc);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkVertexInputAttributeDescription vertexAttributeDesc = {};
|
|
|
|
vertexAttributeDesc.format = VK_FORMAT_R32_UINT;
|
|
|
|
vertexAttributeDesc.offset = offsetof(PRIM_VERTEX, z);
|
|
|
|
vertexAttributeDesc.location = VERTEX_ATTRIB_LOCATION_DEPTH;
|
|
|
|
vertexAttributes.push_back(vertexAttributeDesc);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkVertexInputAttributeDescription vertexAttributeDesc = {};
|
|
|
|
vertexAttributeDesc.format = VK_FORMAT_R8G8B8A8_UNORM;
|
|
|
|
vertexAttributeDesc.offset = offsetof(PRIM_VERTEX, color);
|
|
|
|
vertexAttributeDesc.location = VERTEX_ATTRIB_LOCATION_COLOR;
|
|
|
|
vertexAttributes.push_back(vertexAttributeDesc);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkVertexInputAttributeDescription vertexAttributeDesc = {};
|
|
|
|
vertexAttributeDesc.format = VK_FORMAT_R32G32B32_SFLOAT;
|
|
|
|
vertexAttributeDesc.offset = offsetof(PRIM_VERTEX, s);
|
|
|
|
vertexAttributeDesc.location = VERTEX_ATTRIB_LOCATION_TEXCOORD;
|
|
|
|
vertexAttributes.push_back(vertexAttributeDesc);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkVertexInputAttributeDescription vertexAttributeDesc = {};
|
|
|
|
vertexAttributeDesc.format = VK_FORMAT_R32_SFLOAT;
|
|
|
|
vertexAttributeDesc.offset = offsetof(PRIM_VERTEX, f);
|
|
|
|
vertexAttributeDesc.location = VERTEX_ATTRIB_LOCATION_FOG;
|
|
|
|
vertexAttributes.push_back(vertexAttributeDesc);
|
|
|
|
}
|
|
|
|
|
|
|
|
VkVertexInputBindingDescription binding = {};
|
|
|
|
binding.stride = sizeof(PRIM_VERTEX);
|
|
|
|
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
|
|
|
|
|
|
auto vertexInputInfo = Framework::Vulkan::PipelineVertexInputStateCreateInfo();
|
|
|
|
vertexInputInfo.vertexBindingDescriptionCount = 1;
|
|
|
|
vertexInputInfo.pVertexBindingDescriptions = &binding;
|
|
|
|
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32>(vertexAttributes.size());
|
|
|
|
vertexInputInfo.pVertexAttributeDescriptions = vertexAttributes.data();
|
|
|
|
|
|
|
|
auto rasterStateInfo = Framework::Vulkan::PipelineRasterizationStateCreateInfo();
|
|
|
|
rasterStateInfo.polygonMode = VK_POLYGON_MODE_FILL;
|
|
|
|
rasterStateInfo.cullMode = VK_CULL_MODE_NONE;
|
|
|
|
rasterStateInfo.lineWidth = 1.0f;
|
|
|
|
|
|
|
|
// Our attachment will write to all color channels, but no blending is enabled.
|
2021-07-13 09:08:19 -04:00
|
|
|
std::vector<VkPipelineColorBlendAttachmentState> blendAttachmentStates;
|
|
|
|
for(uint32 i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
VkPipelineColorBlendAttachmentState blendAttachmentState = {};
|
|
|
|
blendAttachmentState.colorWriteMask = 0xf;
|
|
|
|
blendAttachmentStates.push_back(blendAttachmentState);
|
|
|
|
}
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
auto colorBlendStateInfo = Framework::Vulkan::PipelineColorBlendStateCreateInfo();
|
2021-07-13 09:08:19 -04:00
|
|
|
colorBlendStateInfo.attachmentCount = blendAttachmentStates.size();
|
|
|
|
colorBlendStateInfo.pAttachments = blendAttachmentStates.data();
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
auto viewportStateInfo = Framework::Vulkan::PipelineViewportStateCreateInfo();
|
|
|
|
viewportStateInfo.viewportCount = 1;
|
|
|
|
viewportStateInfo.scissorCount = 1;
|
|
|
|
|
|
|
|
auto depthStencilStateInfo = Framework::Vulkan::PipelineDepthStencilStateCreateInfo();
|
|
|
|
|
|
|
|
auto multisampleStateInfo = Framework::Vulkan::PipelineMultisampleStateCreateInfo();
|
|
|
|
multisampleStateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
|
|
|
|
static const VkDynamicState dynamicStates[] =
|
|
|
|
{
|
|
|
|
VK_DYNAMIC_STATE_VIEWPORT,
|
|
|
|
VK_DYNAMIC_STATE_SCISSOR,
|
|
|
|
};
|
|
|
|
auto dynamicStateInfo = Framework::Vulkan::PipelineDynamicStateCreateInfo();
|
|
|
|
dynamicStateInfo.pDynamicStates = dynamicStates;
|
|
|
|
dynamicStateInfo.dynamicStateCount = sizeof(dynamicStates) / sizeof(dynamicStates[0]);
|
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo shaderStages[2] =
|
|
|
|
{
|
|
|
|
{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO},
|
|
|
|
{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO},
|
|
|
|
};
|
|
|
|
|
|
|
|
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
|
|
|
shaderStages[0].module = vertexShader;
|
|
|
|
shaderStages[0].pName = "main";
|
|
|
|
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
shaderStages[1].module = fragmentShader;
|
|
|
|
shaderStages[1].pName = "main";
|
|
|
|
|
|
|
|
auto pipelineCreateInfo = Framework::Vulkan::GraphicsPipelineCreateInfo();
|
|
|
|
pipelineCreateInfo.stageCount = 2;
|
2021-06-21 10:49:30 -04:00
|
|
|
pipelineCreateInfo.subpass = 1;
|
2021-06-20 15:13:21 -04:00
|
|
|
pipelineCreateInfo.pStages = shaderStages;
|
|
|
|
pipelineCreateInfo.pInputAssemblyState = &inputAssemblyInfo;
|
|
|
|
pipelineCreateInfo.pVertexInputState = &vertexInputInfo;
|
|
|
|
pipelineCreateInfo.pRasterizationState = &rasterStateInfo;
|
|
|
|
pipelineCreateInfo.pColorBlendState = &colorBlendStateInfo;
|
|
|
|
pipelineCreateInfo.pViewportState = &viewportStateInfo;
|
|
|
|
pipelineCreateInfo.pDepthStencilState = &depthStencilStateInfo;
|
|
|
|
pipelineCreateInfo.pMultisampleState = &multisampleStateInfo;
|
|
|
|
pipelineCreateInfo.pDynamicState = &dynamicStateInfo;
|
|
|
|
pipelineCreateInfo.renderPass = m_renderPass;
|
|
|
|
pipelineCreateInfo.layout = drawPipeline.pipelineLayout;
|
|
|
|
|
|
|
|
result = m_context->device.vkCreateGraphicsPipelines(m_context->device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, nullptr, &drawPipeline.pipeline);
|
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
|
|
|
|
return drawPipeline;
|
|
|
|
}
|
|
|
|
|
|
|
|
Framework::Vulkan::CShaderModule CDrawMobile::CreateDrawFragmentShader(const PIPELINE_CAPS& caps)
|
|
|
|
{
|
|
|
|
using namespace Nuanceur;
|
|
|
|
|
|
|
|
auto b = CShaderBuilder();
|
|
|
|
|
|
|
|
{
|
|
|
|
//Inputs
|
|
|
|
auto inputPosition = CFloat4Lvalue(b.CreateInput(Nuanceur::SEMANTIC_SYSTEM_POSITION));
|
|
|
|
auto inputDepth = CFloat4Lvalue(b.CreateInput(Nuanceur::SEMANTIC_TEXCOORD, 1));
|
|
|
|
auto inputColor = CFloat4Lvalue(b.CreateInput(Nuanceur::SEMANTIC_TEXCOORD, 2));
|
|
|
|
auto inputTexCoord = CFloat4Lvalue(b.CreateInput(Nuanceur::SEMANTIC_TEXCOORD, 3));
|
|
|
|
auto inputFog = CFloat4Lvalue(b.CreateInput(Nuanceur::SEMANTIC_TEXCOORD, 4));
|
|
|
|
|
|
|
|
//Outputs
|
2021-08-15 14:22:45 -04:00
|
|
|
auto outputColor = CUintLvalue(b.CreateOutputUint(Nuanceur::SEMANTIC_SYSTEM_COLOR, 0));
|
2021-07-13 09:08:19 -04:00
|
|
|
auto outputDepth = CUintLvalue(b.CreateOutputUint(Nuanceur::SEMANTIC_SYSTEM_COLOR, 1));
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
auto memoryBuffer = CArrayUintValue(b.CreateUniformArrayUint("memoryBuffer", DESCRIPTOR_LOCATION_BUFFER_MEMORY, Nuanceur::SYMBOL_ATTRIBUTE_COHERENT));
|
|
|
|
auto clutBuffer = CArrayUintValue(b.CreateUniformArrayUint("clutBuffer", DESCRIPTOR_LOCATION_IMAGE_CLUT));
|
|
|
|
auto texSwizzleTable = CImageUint2DValue(b.CreateImage2DUint(DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_TEX));
|
|
|
|
auto fbSwizzleTable = CImageUint2DValue(b.CreateImage2DUint(DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_FB));
|
|
|
|
auto depthSwizzleTable = CImageUint2DValue(b.CreateImage2DUint(DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_DEPTH));
|
2021-08-15 14:22:45 -04:00
|
|
|
auto subpassColorInput = CSubpassInputUintValue(b.CreateSubpassInputUint(DESCRIPTOR_LOCATION_IMAGE_INPUT_COLOR, 0));
|
2021-07-13 09:08:19 -04:00
|
|
|
auto subpassDepthInput = CSubpassInputUintValue(b.CreateSubpassInputUint(DESCRIPTOR_LOCATION_IMAGE_INPUT_DEPTH, 1));
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
//Push constants
|
|
|
|
auto fbDepthParams = CInt4Lvalue(b.CreateUniformInt4("fbDepthParams", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
|
|
|
auto texParams0 = CInt4Lvalue(b.CreateUniformInt4("texParams0", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
|
|
|
auto texParams1 = CInt4Lvalue(b.CreateUniformInt4("texParams1", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
|
|
|
auto texParams2 = CInt4Lvalue(b.CreateUniformInt4("texParams2", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
|
|
|
auto alphaFbParams = CInt4Lvalue(b.CreateUniformInt4("alphaFbParams", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
|
|
|
auto fogColor = CFloat4Lvalue(b.CreateUniformFloat4("fogColor", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
|
|
|
|
|
|
|
auto fbBufAddress = fbDepthParams->x();
|
|
|
|
auto fbBufWidth = fbDepthParams->y();
|
|
|
|
auto depthBufAddress = fbDepthParams->z();
|
|
|
|
auto depthBufWidth = fbDepthParams->w();
|
|
|
|
|
|
|
|
auto texBufAddress = texParams0->x();
|
|
|
|
auto texBufWidth = texParams0->y();
|
|
|
|
auto texSize = texParams0->zw();
|
|
|
|
|
|
|
|
auto texCsa = texParams1->x();
|
|
|
|
auto texA0 = ToFloat(texParams1->y()) / NewFloat(b, 255.f);
|
|
|
|
auto texA1 = ToFloat(texParams1->z()) / NewFloat(b, 255.f);
|
|
|
|
|
|
|
|
auto clampMin = texParams2->xy();
|
|
|
|
auto clampMax = texParams2->zw();
|
|
|
|
|
2021-08-15 14:22:45 -04:00
|
|
|
auto fbWriteMask = ToUint(alphaFbParams->x());
|
|
|
|
auto alphaFix = alphaFbParams->y();
|
|
|
|
auto alphaRef = alphaFbParams->z();
|
2021-06-20 15:13:21 -04:00
|
|
|
|
2021-07-13 09:08:19 -04:00
|
|
|
auto srcDepth = ToUint(inputDepth->x() * NewFloat(b, DEPTH_MAX));
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
//TODO: Try vectorized shift
|
|
|
|
//auto imageColor = ToUint(inputColor * NewFloat4(b, 255.f, 255.f, 255.f, 255.f));
|
|
|
|
|
|
|
|
auto textureColor = CFloat4Lvalue(b.CreateVariableFloat("textureColor"));
|
|
|
|
textureColor = NewFloat4(b, 1, 1, 1, 1);
|
|
|
|
|
|
|
|
if(caps.hasTexture)
|
|
|
|
{
|
|
|
|
auto clampCoordinates =
|
|
|
|
[&](CInt2Value textureIuv) {
|
2021-09-18 11:56:54 -04:00
|
|
|
auto clampU = CDrawUtils::ClampTexCoord(b, caps.texClampU, textureIuv->x(), texSize->x(), clampMin->x(), clampMax->x());
|
|
|
|
auto clampV = CDrawUtils::ClampTexCoord(b, caps.texClampV, textureIuv->y(), texSize->y(), clampMin->y(), clampMax->y());
|
2021-06-20 15:13:21 -04:00
|
|
|
return NewInt2(clampU, clampV);
|
|
|
|
};
|
|
|
|
|
|
|
|
auto getTextureColor =
|
|
|
|
[&](CInt2Value textureIuv, CFloat4Lvalue& textureColor) {
|
2021-09-18 11:56:54 -04:00
|
|
|
textureColor = CDrawUtils::GetTextureColor(b, caps.textureFormat, caps.clutFormat, textureIuv,
|
2021-09-25 10:31:27 -04:00
|
|
|
memoryBuffer, clutBuffer, texSwizzleTable, texBufAddress, texBufWidth, texCsa);
|
2021-06-20 15:13:21 -04:00
|
|
|
if(caps.textureHasAlpha)
|
|
|
|
{
|
2021-09-18 11:56:54 -04:00
|
|
|
CDrawUtils::ExpandAlpha(b, caps.textureFormat, caps.clutFormat, caps.textureBlackIsTransparent, textureColor, texA0, texA1);
|
2021-06-20 15:13:21 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
auto textureSt = CFloat2Lvalue(b.CreateVariableFloat("textureSt"));
|
|
|
|
textureSt = inputTexCoord->xy() / inputTexCoord->zz();
|
|
|
|
|
|
|
|
if(caps.textureUseLinearFiltering)
|
|
|
|
{
|
|
|
|
//Linear Sampling
|
|
|
|
//-------------------------------------
|
|
|
|
|
|
|
|
auto textureLinearPos = CFloat2Lvalue(b.CreateVariableFloat("textureLinearPos"));
|
|
|
|
auto textureLinearAb = CFloat2Lvalue(b.CreateVariableFloat("textureLinearAb"));
|
|
|
|
auto textureIuv0 = CInt2Lvalue(b.CreateVariableInt("textureIuv0"));
|
|
|
|
auto textureIuv1 = CInt2Lvalue(b.CreateVariableInt("textureIuv1"));
|
|
|
|
auto textureColorA = CFloat4Lvalue(b.CreateVariableFloat("textureColorA"));
|
|
|
|
auto textureColorB = CFloat4Lvalue(b.CreateVariableFloat("textureColorB"));
|
|
|
|
auto textureColorC = CFloat4Lvalue(b.CreateVariableFloat("textureColorC"));
|
|
|
|
auto textureColorD = CFloat4Lvalue(b.CreateVariableFloat("textureColorD"));
|
|
|
|
|
|
|
|
textureLinearPos = (textureSt * ToFloat(texSize)) + NewFloat2(b, -0.5f, -0.5f);
|
|
|
|
textureLinearAb = Fract(textureLinearPos);
|
|
|
|
|
|
|
|
textureIuv0 = ToInt(textureLinearPos);
|
|
|
|
textureIuv1 = textureIuv0 + NewInt2(b, 1, 1);
|
|
|
|
|
|
|
|
auto textureClampIuv0 = clampCoordinates(textureIuv0);
|
|
|
|
auto textureClampIuv1 = clampCoordinates(textureIuv1);
|
|
|
|
|
|
|
|
getTextureColor(NewInt2(textureClampIuv0->x(), textureClampIuv0->y()), textureColorA);
|
|
|
|
getTextureColor(NewInt2(textureClampIuv1->x(), textureClampIuv0->y()), textureColorB);
|
|
|
|
getTextureColor(NewInt2(textureClampIuv0->x(), textureClampIuv1->y()), textureColorC);
|
|
|
|
getTextureColor(NewInt2(textureClampIuv1->x(), textureClampIuv1->y()), textureColorD);
|
|
|
|
|
|
|
|
auto factorA = (NewFloat(b, 1.0f) - textureLinearAb->x()) * (NewFloat(b, 1.0f) - textureLinearAb->y());
|
|
|
|
auto factorB = textureLinearAb->x() * (NewFloat(b, 1.0f) - textureLinearAb->y());
|
|
|
|
auto factorC = (NewFloat(b, 1.0f) - textureLinearAb->x()) * textureLinearAb->y();
|
|
|
|
auto factorD = textureLinearAb->x() * textureLinearAb->y();
|
|
|
|
|
|
|
|
textureColor =
|
|
|
|
textureColorA * factorA->xxxx() +
|
|
|
|
textureColorB * factorB->xxxx() +
|
|
|
|
textureColorC * factorC->xxxx() +
|
|
|
|
textureColorD * factorD->xxxx();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//Point Sampling
|
|
|
|
//------------------------------
|
|
|
|
auto texelPos = ToInt(textureSt * ToFloat(texSize));
|
|
|
|
auto clampTexPos = clampCoordinates(texelPos);
|
|
|
|
getTextureColor(clampTexPos, textureColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(caps.textureFunction)
|
|
|
|
{
|
|
|
|
case CGSHandler::TEX0_FUNCTION_MODULATE:
|
|
|
|
textureColor = textureColor * inputColor * NewFloat4(b, 2, 2, 2, 2);
|
|
|
|
textureColor = Clamp(textureColor, NewFloat4(b, 0, 0, 0, 0), NewFloat4(b, 1, 1, 1, 1));
|
|
|
|
if(!caps.textureHasAlpha)
|
|
|
|
{
|
|
|
|
textureColor = NewFloat4(textureColor->xyz(), inputColor->w());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CGSHandler::TEX0_FUNCTION_DECAL:
|
|
|
|
//Nothing to do
|
|
|
|
break;
|
|
|
|
case CGSHandler::TEX0_FUNCTION_HIGHLIGHT:
|
|
|
|
{
|
|
|
|
auto tempColor = (textureColor->xyz() * inputColor->xyz() * NewFloat3(b, 2, 2, 2)) + inputColor->www();
|
|
|
|
if(caps.textureHasAlpha)
|
|
|
|
{
|
|
|
|
textureColor = NewFloat4(tempColor, inputColor->w() + textureColor->w());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
textureColor = NewFloat4(tempColor, inputColor->w());
|
|
|
|
}
|
|
|
|
textureColor = Clamp(textureColor, NewFloat4(b, 0, 0, 0, 0), NewFloat4(b, 1, 1, 1, 1));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CGSHandler::TEX0_FUNCTION_HIGHLIGHT2:
|
|
|
|
{
|
|
|
|
auto tempColor = (textureColor->xyz() * inputColor->xyz() * NewFloat3(b, 2, 2, 2)) + inputColor->www();
|
|
|
|
if(caps.textureHasAlpha)
|
|
|
|
{
|
|
|
|
textureColor = NewFloat4(tempColor, textureColor->w());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
textureColor = NewFloat4(tempColor, inputColor->w());
|
|
|
|
}
|
|
|
|
textureColor = Clamp(textureColor, NewFloat4(b, 0, 0, 0, 0), NewFloat4(b, 1, 1, 1, 1));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
textureColor = inputColor->xyzw();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto writeColor = CBoolLvalue(b.CreateVariableBool("writeColor"));
|
|
|
|
auto writeDepth = CBoolLvalue(b.CreateVariableBool("writeDepth"));
|
|
|
|
auto writeAlpha = CBoolLvalue(b.CreateVariableBool("writeAlpha"));
|
|
|
|
|
|
|
|
writeColor = NewBool(b, true);
|
|
|
|
writeDepth = NewBool(b, true);
|
|
|
|
writeAlpha = NewBool(b, true);
|
|
|
|
|
|
|
|
if(caps.hasFog)
|
|
|
|
{
|
|
|
|
auto fogMixColor = Mix(textureColor->xyz(), fogColor->xyz(), inputFog->xxx());
|
|
|
|
textureColor = NewFloat4(fogMixColor, textureColor->w());
|
|
|
|
}
|
|
|
|
|
|
|
|
auto screenPos = ToInt(inputPosition->xy());
|
|
|
|
|
|
|
|
switch(caps.scanMask)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
[[fallthrough]];
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
auto write = (screenPos->y() & NewInt(b, 1)) != NewInt(b, 0);
|
|
|
|
writeColor = write;
|
|
|
|
writeDepth = write;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
{
|
|
|
|
auto write = (screenPos->y() & NewInt(b, 1)) == NewInt(b, 0);
|
|
|
|
writeColor = write;
|
|
|
|
writeDepth = write;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-08-15 14:22:45 -04:00
|
|
|
auto srcIColor = CInt4Lvalue(b.CreateVariableInt("srcIColor"));
|
|
|
|
srcIColor = ToInt(textureColor->xyzw() * NewFloat4(b, 255.f, 255.f, 255.f, 255.f));
|
|
|
|
|
2021-09-18 11:56:54 -04:00
|
|
|
CDrawUtils::AlphaTest(b, caps.alphaTestFunction, caps.alphaTestFailAction, srcIColor, alphaRef,
|
2021-09-25 10:31:27 -04:00
|
|
|
writeColor, writeDepth, writeAlpha);
|
2021-08-15 14:22:45 -04:00
|
|
|
|
|
|
|
bool canDiscardAlpha =
|
2021-09-10 16:06:20 -04:00
|
|
|
(caps.alphaTestFunction != CGSHandler::ALPHA_TEST_ALWAYS) &&
|
|
|
|
(caps.alphaTestFailAction == CGSHandler::ALPHA_TEST_FAIL_RGBONLY);
|
2021-08-15 14:22:45 -04:00
|
|
|
|
2021-06-22 13:17:10 -04:00
|
|
|
//BeginInvocationInterlock(b);
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
auto dstPixel = CUintLvalue(b.CreateVariableUint("dstPixel"));
|
2021-07-13 09:08:19 -04:00
|
|
|
auto dstDepth = CUintLvalue(b.CreateVariableUint("dstDepth"));
|
2021-08-15 14:22:45 -04:00
|
|
|
auto dstIColor = CInt4Lvalue(b.CreateVariableInt("dstIColor"));
|
2021-06-23 20:27:14 -04:00
|
|
|
|
2021-08-15 14:22:45 -04:00
|
|
|
auto finalPixel = CUintLvalue(b.CreateVariableUint("finalPixel"));
|
2021-07-13 09:08:19 -04:00
|
|
|
auto finalDepth = CUintLvalue(b.CreateVariableUint("finalDepth"));
|
2021-08-15 14:22:45 -04:00
|
|
|
auto finalIColor = CInt4Lvalue(b.CreateVariableInt("finalIColor"));
|
2021-06-20 15:13:21 -04:00
|
|
|
|
2021-08-15 14:22:45 -04:00
|
|
|
dstPixel = Load(subpassColorInput, NewInt2(b, 0, 0))->x();
|
2021-07-13 09:08:19 -04:00
|
|
|
dstDepth = Load(subpassDepthInput, NewInt2(b, 0, 0))->x();
|
2021-08-15 14:22:45 -04:00
|
|
|
|
|
|
|
switch(caps.framebufferFormat)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
[[fallthrough]];
|
|
|
|
case CGSHandler::PSMCT32:
|
|
|
|
{
|
|
|
|
dstIColor = CMemoryUtils::PSM32ToIVec4(b, dstPixel);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CGSHandler::PSMCT24:
|
|
|
|
{
|
|
|
|
dstIColor = CMemoryUtils::PSM32ToIVec4(b, dstPixel);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CGSHandler::PSMCT16:
|
|
|
|
case CGSHandler::PSMCT16S:
|
|
|
|
{
|
|
|
|
dstIColor = CMemoryUtils::PSM16ToIVec4(b, dstPixel);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
if(caps.hasDstAlphaTest)
|
|
|
|
{
|
2021-09-18 11:56:54 -04:00
|
|
|
CDrawUtils::DestinationAlphaTest(b, caps.framebufferFormat, caps.dstAlphaTestRef, dstPixel, writeColor, writeDepth);
|
2021-06-20 15:13:21 -04:00
|
|
|
}
|
|
|
|
|
2021-08-15 14:22:45 -04:00
|
|
|
auto depthTestResult = CBoolLvalue(b.CreateVariableBool("depthTestResult"));
|
2021-06-20 15:13:21 -04:00
|
|
|
switch(caps.depthTestFunction)
|
|
|
|
{
|
|
|
|
case CGSHandler::DEPTH_TEST_ALWAYS:
|
|
|
|
depthTestResult = NewBool(b, true);
|
|
|
|
break;
|
|
|
|
case CGSHandler::DEPTH_TEST_NEVER:
|
|
|
|
depthTestResult = NewBool(b, false);
|
|
|
|
break;
|
|
|
|
case CGSHandler::DEPTH_TEST_GEQUAL:
|
|
|
|
depthTestResult = srcDepth >= dstDepth;
|
|
|
|
break;
|
|
|
|
case CGSHandler::DEPTH_TEST_GREATER:
|
|
|
|
depthTestResult = srcDepth > dstDepth;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
BeginIf(b, !depthTestResult);
|
|
|
|
{
|
|
|
|
writeColor = NewBool(b, false);
|
|
|
|
writeDepth = NewBool(b, false);
|
|
|
|
}
|
|
|
|
EndIf(b);
|
|
|
|
|
|
|
|
if(caps.hasAlphaBlending)
|
|
|
|
{
|
|
|
|
//Blend
|
2021-09-18 11:56:54 -04:00
|
|
|
auto alphaA = CDrawUtils::GetAlphaABD(b, caps.alphaA, srcIColor, dstIColor);
|
|
|
|
auto alphaB = CDrawUtils::GetAlphaABD(b, caps.alphaB, srcIColor, dstIColor);
|
|
|
|
auto alphaC = CDrawUtils::GetAlphaC(b, caps.alphaC, srcIColor, dstIColor, alphaFix);
|
|
|
|
auto alphaD = CDrawUtils::GetAlphaABD(b, caps.alphaD, srcIColor, dstIColor);
|
2021-08-15 14:22:45 -04:00
|
|
|
|
|
|
|
auto blendedRGB = ShiftRightArithmetic((alphaA - alphaB) * alphaC, NewInt3(b, 7, 7, 7)) + alphaD;
|
|
|
|
auto blendedIColor = NewInt4(blendedRGB, srcIColor->w());
|
|
|
|
if(caps.colClamp)
|
|
|
|
{
|
|
|
|
finalIColor = Clamp(blendedIColor, NewInt4(b, 0, 0, 0, 0), NewInt4(b, 255, 255, 255, 255));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
finalIColor = blendedIColor & NewInt4(b, 255, 255, 255, 255);
|
|
|
|
}
|
2021-06-20 15:13:21 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-08-15 14:22:45 -04:00
|
|
|
finalIColor = srcIColor->xyzw();
|
2021-06-20 15:13:21 -04:00
|
|
|
}
|
|
|
|
|
2021-08-15 14:22:45 -04:00
|
|
|
if(caps.fba)
|
|
|
|
{
|
|
|
|
finalIColor = NewInt4(finalIColor->xyz(), finalIColor->w() | NewInt(b, 0x80));
|
|
|
|
}
|
|
|
|
|
|
|
|
if(canDiscardAlpha)
|
|
|
|
{
|
|
|
|
BeginIf(b, !writeAlpha);
|
|
|
|
{
|
|
|
|
finalIColor = NewInt4(finalIColor->xyz(), dstIColor->w());
|
|
|
|
}
|
|
|
|
EndIf(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(caps.framebufferFormat)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
[[fallthrough]];
|
|
|
|
case CGSHandler::PSMCT32:
|
|
|
|
case CGSHandler::PSMCT24:
|
|
|
|
{
|
|
|
|
finalPixel = CMemoryUtils::IVec4ToPSM32(b, finalIColor);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CGSHandler::PSMCT16:
|
|
|
|
case CGSHandler::PSMCT16S:
|
|
|
|
{
|
|
|
|
finalPixel = CMemoryUtils::IVec4ToPSM16(b, finalIColor);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
finalPixel = (finalPixel & fbWriteMask) | (dstPixel & ~fbWriteMask);
|
2021-06-23 08:12:07 -04:00
|
|
|
|
2021-06-22 14:36:16 -04:00
|
|
|
BeginIf(b, !writeColor);
|
|
|
|
{
|
2021-08-15 14:22:45 -04:00
|
|
|
finalPixel = dstPixel->x();
|
2021-06-22 14:36:16 -04:00
|
|
|
}
|
|
|
|
EndIf(b);
|
|
|
|
|
2021-08-15 14:22:45 -04:00
|
|
|
finalDepth = srcDepth->x();
|
2021-06-23 08:12:07 -04:00
|
|
|
BeginIf(b, !writeDepth);
|
|
|
|
{
|
|
|
|
finalDepth = dstDepth->x();
|
|
|
|
}
|
|
|
|
EndIf(b);
|
|
|
|
|
2021-07-25 20:56:08 -04:00
|
|
|
if(!caps.writeDepth)
|
|
|
|
{
|
|
|
|
finalDepth = dstDepth->x();
|
|
|
|
}
|
2021-09-10 16:06:20 -04:00
|
|
|
|
2021-06-22 13:17:10 -04:00
|
|
|
//EndInvocationInterlock(b);
|
2021-06-20 15:13:21 -04:00
|
|
|
|
2021-08-15 14:22:45 -04:00
|
|
|
outputColor = finalPixel->x();
|
2021-06-23 08:12:07 -04:00
|
|
|
outputDepth = finalDepth->x();
|
2021-06-20 15:13:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Framework::CMemStream shaderStream;
|
|
|
|
Nuanceur::CSpirvShaderGenerator::Generate(shaderStream, b, Nuanceur::CSpirvShaderGenerator::SHADER_TYPE_FRAGMENT);
|
|
|
|
shaderStream.Seek(0, Framework::STREAM_SEEK_SET);
|
|
|
|
return Framework::Vulkan::CShaderModule(m_context->device, shaderStream);
|
|
|
|
}
|
|
|
|
|
2021-07-27 10:56:13 -04:00
|
|
|
CDrawMobile::PIPELINE_CAPS CDrawMobile::MakeLoadStorePipelineCaps(const PIPELINE_CAPS& caps)
|
|
|
|
{
|
|
|
|
auto strippedCaps = make_convertible<PIPELINE_CAPS>(0);
|
|
|
|
strippedCaps.framebufferFormat = caps.framebufferFormat;
|
|
|
|
strippedCaps.depthbufferFormat = caps.depthbufferFormat;
|
|
|
|
strippedCaps.writeDepth = caps.writeDepth;
|
|
|
|
return strippedCaps;
|
|
|
|
}
|
|
|
|
|
2021-07-19 12:59:36 -04:00
|
|
|
PIPELINE CDrawMobile::CreateLoadPipeline(const PIPELINE_CAPS& caps)
|
2021-06-20 15:13:21 -04:00
|
|
|
{
|
|
|
|
PIPELINE loadPipeline;
|
|
|
|
|
|
|
|
auto vertexShader = CreateLoadStoreVertexShader();
|
2021-07-19 12:59:36 -04:00
|
|
|
auto fragmentShader = CreateLoadFragmentShader(caps);
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
auto result = VK_SUCCESS;
|
|
|
|
|
|
|
|
{
|
|
|
|
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings;
|
|
|
|
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_BUFFER_MEMORY;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_FB;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_DEPTH;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
2021-06-22 14:04:39 -04:00
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_INPUT_COLOR;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
2021-06-23 08:12:07 -04:00
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_INPUT_DEPTH;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
auto setLayoutCreateInfo = Framework::Vulkan::DescriptorSetLayoutCreateInfo();
|
|
|
|
setLayoutCreateInfo.bindingCount = static_cast<uint32>(setLayoutBindings.size());
|
|
|
|
setLayoutCreateInfo.pBindings = setLayoutBindings.data();
|
|
|
|
|
|
|
|
result = m_context->device.vkCreateDescriptorSetLayout(m_context->device, &setLayoutCreateInfo, nullptr, &loadPipeline.descriptorSetLayout);
|
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkPushConstantRange pushConstantInfo = {};
|
|
|
|
pushConstantInfo.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
pushConstantInfo.offset = 0;
|
2021-09-18 11:56:54 -04:00
|
|
|
pushConstantInfo.size = sizeof(DRAW_PIPELINE_PUSHCONSTANTS);
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
auto pipelineLayoutCreateInfo = Framework::Vulkan::PipelineLayoutCreateInfo();
|
|
|
|
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
|
|
|
|
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantInfo;
|
|
|
|
pipelineLayoutCreateInfo.setLayoutCount = 1;
|
|
|
|
pipelineLayoutCreateInfo.pSetLayouts = &loadPipeline.descriptorSetLayout;
|
|
|
|
|
|
|
|
result = m_context->device.vkCreatePipelineLayout(m_context->device, &pipelineLayoutCreateInfo, nullptr, &loadPipeline.pipelineLayout);
|
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto inputAssemblyInfo = Framework::Vulkan::PipelineInputAssemblyStateCreateInfo();
|
|
|
|
inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
|
|
|
|
|
|
|
auto vertexInputInfo = Framework::Vulkan::PipelineVertexInputStateCreateInfo();
|
|
|
|
|
|
|
|
auto rasterStateInfo = Framework::Vulkan::PipelineRasterizationStateCreateInfo();
|
|
|
|
rasterStateInfo.polygonMode = VK_POLYGON_MODE_FILL;
|
|
|
|
rasterStateInfo.cullMode = VK_CULL_MODE_NONE;
|
|
|
|
rasterStateInfo.lineWidth = 1.0f;
|
|
|
|
|
|
|
|
// Our attachment will write to all color channels, but no blending is enabled.
|
2021-07-13 09:08:19 -04:00
|
|
|
std::vector<VkPipelineColorBlendAttachmentState> blendAttachmentStates;
|
|
|
|
for(uint32 i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
VkPipelineColorBlendAttachmentState blendAttachmentState = {};
|
|
|
|
blendAttachmentState.colorWriteMask = 0xf;
|
|
|
|
blendAttachmentStates.push_back(blendAttachmentState);
|
|
|
|
}
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
auto colorBlendStateInfo = Framework::Vulkan::PipelineColorBlendStateCreateInfo();
|
2021-07-13 09:08:19 -04:00
|
|
|
colorBlendStateInfo.attachmentCount = blendAttachmentStates.size();
|
|
|
|
colorBlendStateInfo.pAttachments = blendAttachmentStates.data();
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
auto viewportStateInfo = Framework::Vulkan::PipelineViewportStateCreateInfo();
|
|
|
|
viewportStateInfo.viewportCount = 1;
|
|
|
|
viewportStateInfo.scissorCount = 1;
|
|
|
|
|
|
|
|
auto depthStencilStateInfo = Framework::Vulkan::PipelineDepthStencilStateCreateInfo();
|
2021-06-23 08:12:07 -04:00
|
|
|
depthStencilStateInfo.depthTestEnable = 1;
|
|
|
|
depthStencilStateInfo.depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
|
|
|
depthStencilStateInfo.depthWriteEnable = 1;
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
auto multisampleStateInfo = Framework::Vulkan::PipelineMultisampleStateCreateInfo();
|
|
|
|
multisampleStateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
|
|
|
|
static const VkDynamicState dynamicStates[] =
|
2021-06-21 17:33:19 -04:00
|
|
|
{
|
|
|
|
VK_DYNAMIC_STATE_VIEWPORT,
|
|
|
|
VK_DYNAMIC_STATE_SCISSOR,
|
|
|
|
};
|
2021-06-20 15:13:21 -04:00
|
|
|
auto dynamicStateInfo = Framework::Vulkan::PipelineDynamicStateCreateInfo();
|
|
|
|
dynamicStateInfo.pDynamicStates = dynamicStates;
|
|
|
|
dynamicStateInfo.dynamicStateCount = sizeof(dynamicStates) / sizeof(dynamicStates[0]);
|
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo shaderStages[2] =
|
2021-06-21 17:33:19 -04:00
|
|
|
{
|
|
|
|
{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO},
|
|
|
|
{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO},
|
|
|
|
};
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
|
|
|
shaderStages[0].module = vertexShader;
|
|
|
|
shaderStages[0].pName = "main";
|
|
|
|
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
shaderStages[1].module = fragmentShader;
|
|
|
|
shaderStages[1].pName = "main";
|
|
|
|
|
|
|
|
auto pipelineCreateInfo = Framework::Vulkan::GraphicsPipelineCreateInfo();
|
|
|
|
pipelineCreateInfo.stageCount = 2;
|
2021-06-21 17:33:19 -04:00
|
|
|
pipelineCreateInfo.subpass = 0;
|
2021-06-20 15:13:21 -04:00
|
|
|
pipelineCreateInfo.pStages = shaderStages;
|
|
|
|
pipelineCreateInfo.pInputAssemblyState = &inputAssemblyInfo;
|
|
|
|
pipelineCreateInfo.pVertexInputState = &vertexInputInfo;
|
|
|
|
pipelineCreateInfo.pRasterizationState = &rasterStateInfo;
|
|
|
|
pipelineCreateInfo.pColorBlendState = &colorBlendStateInfo;
|
|
|
|
pipelineCreateInfo.pViewportState = &viewportStateInfo;
|
|
|
|
pipelineCreateInfo.pDepthStencilState = &depthStencilStateInfo;
|
|
|
|
pipelineCreateInfo.pMultisampleState = &multisampleStateInfo;
|
|
|
|
pipelineCreateInfo.pDynamicState = &dynamicStateInfo;
|
|
|
|
pipelineCreateInfo.renderPass = m_renderPass;
|
|
|
|
pipelineCreateInfo.layout = loadPipeline.pipelineLayout;
|
|
|
|
|
|
|
|
result = m_context->device.vkCreateGraphicsPipelines(m_context->device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, nullptr, &loadPipeline.pipeline);
|
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
|
|
|
|
return loadPipeline;
|
|
|
|
}
|
|
|
|
|
2021-07-19 12:59:36 -04:00
|
|
|
PIPELINE CDrawMobile::CreateStorePipeline(const PIPELINE_CAPS& caps)
|
2021-06-21 17:33:19 -04:00
|
|
|
{
|
|
|
|
PIPELINE storePipeline;
|
|
|
|
|
|
|
|
auto vertexShader = CreateLoadStoreVertexShader();
|
2021-07-19 12:59:36 -04:00
|
|
|
auto fragmentShader = CreateStoreFragmentShader(caps);
|
2021-06-21 17:33:19 -04:00
|
|
|
|
|
|
|
auto result = VK_SUCCESS;
|
|
|
|
|
|
|
|
{
|
|
|
|
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings;
|
|
|
|
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_BUFFER_MEMORY;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_FB;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_DEPTH;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
2021-06-21 18:40:21 -04:00
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_INPUT_COLOR;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
2021-06-23 08:12:07 -04:00
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding setLayoutBinding = {};
|
|
|
|
setLayoutBinding.binding = DESCRIPTOR_LOCATION_IMAGE_INPUT_DEPTH;
|
|
|
|
setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
|
|
|
setLayoutBinding.descriptorCount = 1;
|
|
|
|
setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
setLayoutBindings.push_back(setLayoutBinding);
|
|
|
|
}
|
|
|
|
|
2021-06-21 17:33:19 -04:00
|
|
|
auto setLayoutCreateInfo = Framework::Vulkan::DescriptorSetLayoutCreateInfo();
|
|
|
|
setLayoutCreateInfo.bindingCount = static_cast<uint32>(setLayoutBindings.size());
|
|
|
|
setLayoutCreateInfo.pBindings = setLayoutBindings.data();
|
|
|
|
|
|
|
|
result = m_context->device.vkCreateDescriptorSetLayout(m_context->device, &setLayoutCreateInfo, nullptr, &storePipeline.descriptorSetLayout);
|
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
VkPushConstantRange pushConstantInfo = {};
|
|
|
|
pushConstantInfo.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
pushConstantInfo.offset = 0;
|
2021-09-18 11:56:54 -04:00
|
|
|
pushConstantInfo.size = sizeof(DRAW_PIPELINE_PUSHCONSTANTS);
|
2021-06-21 17:33:19 -04:00
|
|
|
|
|
|
|
auto pipelineLayoutCreateInfo = Framework::Vulkan::PipelineLayoutCreateInfo();
|
|
|
|
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
|
|
|
|
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantInfo;
|
|
|
|
pipelineLayoutCreateInfo.setLayoutCount = 1;
|
|
|
|
pipelineLayoutCreateInfo.pSetLayouts = &storePipeline.descriptorSetLayout;
|
|
|
|
|
|
|
|
result = m_context->device.vkCreatePipelineLayout(m_context->device, &pipelineLayoutCreateInfo, nullptr, &storePipeline.pipelineLayout);
|
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto inputAssemblyInfo = Framework::Vulkan::PipelineInputAssemblyStateCreateInfo();
|
|
|
|
inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
|
|
|
|
|
|
|
auto vertexInputInfo = Framework::Vulkan::PipelineVertexInputStateCreateInfo();
|
|
|
|
|
|
|
|
auto rasterStateInfo = Framework::Vulkan::PipelineRasterizationStateCreateInfo();
|
|
|
|
rasterStateInfo.polygonMode = VK_POLYGON_MODE_FILL;
|
|
|
|
rasterStateInfo.cullMode = VK_CULL_MODE_NONE;
|
|
|
|
rasterStateInfo.lineWidth = 1.0f;
|
|
|
|
|
|
|
|
// Our attachment will write to all color channels, but no blending is enabled.
|
2021-07-13 09:08:19 -04:00
|
|
|
std::vector<VkPipelineColorBlendAttachmentState> blendAttachmentStates;
|
|
|
|
for(uint32 i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
VkPipelineColorBlendAttachmentState blendAttachmentState = {};
|
|
|
|
blendAttachmentState.colorWriteMask = 0xf;
|
|
|
|
blendAttachmentStates.push_back(blendAttachmentState);
|
|
|
|
}
|
2021-06-21 17:33:19 -04:00
|
|
|
|
|
|
|
auto colorBlendStateInfo = Framework::Vulkan::PipelineColorBlendStateCreateInfo();
|
2021-07-13 09:08:19 -04:00
|
|
|
colorBlendStateInfo.attachmentCount = blendAttachmentStates.size();
|
|
|
|
colorBlendStateInfo.pAttachments = blendAttachmentStates.data();
|
2021-06-21 17:33:19 -04:00
|
|
|
|
|
|
|
auto viewportStateInfo = Framework::Vulkan::PipelineViewportStateCreateInfo();
|
|
|
|
viewportStateInfo.viewportCount = 1;
|
|
|
|
viewportStateInfo.scissorCount = 1;
|
|
|
|
|
|
|
|
auto depthStencilStateInfo = Framework::Vulkan::PipelineDepthStencilStateCreateInfo();
|
2021-06-23 08:12:07 -04:00
|
|
|
depthStencilStateInfo.depthTestEnable = 1;
|
|
|
|
depthStencilStateInfo.depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
|
|
|
depthStencilStateInfo.depthWriteEnable = 1;
|
2021-06-21 17:33:19 -04:00
|
|
|
|
|
|
|
auto multisampleStateInfo = Framework::Vulkan::PipelineMultisampleStateCreateInfo();
|
|
|
|
multisampleStateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
|
|
|
|
static const VkDynamicState dynamicStates[] =
|
|
|
|
{
|
|
|
|
VK_DYNAMIC_STATE_VIEWPORT,
|
|
|
|
VK_DYNAMIC_STATE_SCISSOR,
|
|
|
|
};
|
|
|
|
auto dynamicStateInfo = Framework::Vulkan::PipelineDynamicStateCreateInfo();
|
|
|
|
dynamicStateInfo.pDynamicStates = dynamicStates;
|
|
|
|
dynamicStateInfo.dynamicStateCount = sizeof(dynamicStates) / sizeof(dynamicStates[0]);
|
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo shaderStages[2] =
|
|
|
|
{
|
|
|
|
{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO},
|
|
|
|
{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO},
|
|
|
|
};
|
|
|
|
|
|
|
|
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
|
|
|
shaderStages[0].module = vertexShader;
|
|
|
|
shaderStages[0].pName = "main";
|
|
|
|
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
shaderStages[1].module = fragmentShader;
|
|
|
|
shaderStages[1].pName = "main";
|
|
|
|
|
|
|
|
auto pipelineCreateInfo = Framework::Vulkan::GraphicsPipelineCreateInfo();
|
|
|
|
pipelineCreateInfo.stageCount = 2;
|
|
|
|
pipelineCreateInfo.subpass = 2;
|
|
|
|
pipelineCreateInfo.pStages = shaderStages;
|
|
|
|
pipelineCreateInfo.pInputAssemblyState = &inputAssemblyInfo;
|
|
|
|
pipelineCreateInfo.pVertexInputState = &vertexInputInfo;
|
|
|
|
pipelineCreateInfo.pRasterizationState = &rasterStateInfo;
|
|
|
|
pipelineCreateInfo.pColorBlendState = &colorBlendStateInfo;
|
|
|
|
pipelineCreateInfo.pViewportState = &viewportStateInfo;
|
|
|
|
pipelineCreateInfo.pDepthStencilState = &depthStencilStateInfo;
|
|
|
|
pipelineCreateInfo.pMultisampleState = &multisampleStateInfo;
|
|
|
|
pipelineCreateInfo.pDynamicState = &dynamicStateInfo;
|
|
|
|
pipelineCreateInfo.renderPass = m_renderPass;
|
|
|
|
pipelineCreateInfo.layout = storePipeline.pipelineLayout;
|
|
|
|
|
|
|
|
result = m_context->device.vkCreateGraphicsPipelines(m_context->device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, nullptr, &storePipeline.pipeline);
|
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
|
|
|
|
return storePipeline;
|
|
|
|
}
|
|
|
|
|
2021-06-20 15:13:21 -04:00
|
|
|
Framework::Vulkan::CShaderModule CDrawMobile::CreateLoadStoreVertexShader()
|
|
|
|
{
|
|
|
|
using namespace Nuanceur;
|
|
|
|
|
|
|
|
auto b = CShaderBuilder();
|
|
|
|
|
|
|
|
{
|
|
|
|
//Vertex Inputs
|
2021-06-21 17:33:19 -04:00
|
|
|
auto vertexIndex = CIntLvalue(b.CreateInputInt(Nuanceur::SEMANTIC_SYSTEM_VERTEXINDEX));
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
//Outputs
|
|
|
|
auto outputPosition = CFloat4Lvalue(b.CreateOutput(Nuanceur::SEMANTIC_SYSTEM_POSITION));
|
|
|
|
|
2021-06-21 17:33:19 -04:00
|
|
|
auto position = NewFloat2(
|
|
|
|
ToFloat(vertexIndex << NewInt(b, 1) & NewInt(b, 2)),
|
|
|
|
ToFloat(vertexIndex & NewInt(b, 2)));
|
|
|
|
outputPosition = NewFloat4(
|
|
|
|
position->x() * NewFloat(b, 2) + NewFloat(b, -1),
|
|
|
|
position->y() * NewFloat(b, 2) + NewFloat(b, -1),
|
|
|
|
NewFloat(b, 0),
|
|
|
|
NewFloat(b, 1));
|
2021-06-20 15:13:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Framework::CMemStream shaderStream;
|
|
|
|
Nuanceur::CSpirvShaderGenerator::Generate(shaderStream, b, Nuanceur::CSpirvShaderGenerator::SHADER_TYPE_VERTEX);
|
|
|
|
shaderStream.Seek(0, Framework::STREAM_SEEK_SET);
|
|
|
|
return Framework::Vulkan::CShaderModule(m_context->device, shaderStream);
|
|
|
|
}
|
|
|
|
|
2021-07-19 12:59:36 -04:00
|
|
|
Framework::Vulkan::CShaderModule CDrawMobile::CreateLoadFragmentShader(const PIPELINE_CAPS& caps)
|
2021-06-20 15:13:21 -04:00
|
|
|
{
|
|
|
|
using namespace Nuanceur;
|
|
|
|
|
|
|
|
auto b = CShaderBuilder();
|
|
|
|
|
|
|
|
{
|
|
|
|
//Inputs
|
|
|
|
auto inputPosition = CFloat4Lvalue(b.CreateInput(Nuanceur::SEMANTIC_SYSTEM_POSITION));
|
|
|
|
|
|
|
|
//Outputs
|
2021-08-15 14:22:45 -04:00
|
|
|
auto outputColor = CUintLvalue(b.CreateOutputUint(Nuanceur::SEMANTIC_SYSTEM_COLOR, 0));
|
2021-07-13 09:08:19 -04:00
|
|
|
auto outputDepth = CUintLvalue(b.CreateOutputUint(Nuanceur::SEMANTIC_SYSTEM_COLOR, 1));
|
2021-06-20 15:13:21 -04:00
|
|
|
|
|
|
|
auto memoryBuffer = CArrayUintValue(b.CreateUniformArrayUint("memoryBuffer", DESCRIPTOR_LOCATION_BUFFER_MEMORY, Nuanceur::SYMBOL_ATTRIBUTE_COHERENT));
|
|
|
|
auto fbSwizzleTable = CImageUint2DValue(b.CreateImage2DUint(DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_FB));
|
|
|
|
auto depthSwizzleTable = CImageUint2DValue(b.CreateImage2DUint(DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_DEPTH));
|
|
|
|
|
|
|
|
//Push constants
|
|
|
|
auto fbDepthParams = CInt4Lvalue(b.CreateUniformInt4("fbDepthParams", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
|
|
|
|
|
|
|
auto fbBufAddress = fbDepthParams->x();
|
|
|
|
auto fbBufWidth = fbDepthParams->y();
|
|
|
|
auto depthBufAddress = fbDepthParams->z();
|
|
|
|
auto depthBufWidth = fbDepthParams->w();
|
|
|
|
|
2021-06-22 14:04:39 -04:00
|
|
|
auto dstPixel = CUintLvalue(b.CreateVariableUint("dstPixel"));
|
2021-07-13 09:08:19 -04:00
|
|
|
auto dstDepth = CUintLvalue(b.CreateVariableUint("dstDepth"));
|
2021-06-22 14:04:39 -04:00
|
|
|
|
|
|
|
auto fbAddress = CIntLvalue(b.CreateTemporaryInt());
|
|
|
|
auto depthAddress = CIntLvalue(b.CreateTemporaryInt());
|
|
|
|
|
|
|
|
auto screenPos = ToInt(inputPosition->xy());
|
|
|
|
|
|
|
|
switch(caps.framebufferFormat)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
case CGSHandler::PSMCT32:
|
|
|
|
case CGSHandler::PSMCT24:
|
|
|
|
case CGSHandler::PSMZ24:
|
|
|
|
fbAddress = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMCT32>(
|
|
|
|
b, fbSwizzleTable, fbBufAddress, fbBufWidth, screenPos);
|
|
|
|
break;
|
|
|
|
case CGSHandler::PSMCT16:
|
|
|
|
case CGSHandler::PSMCT16S:
|
|
|
|
fbAddress = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMCT16>(
|
|
|
|
b, fbSwizzleTable, fbBufAddress, fbBufWidth, screenPos);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(caps.depthbufferFormat)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
case CGSHandler::PSMZ32:
|
|
|
|
case CGSHandler::PSMZ24:
|
|
|
|
depthAddress = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMZ32>(
|
|
|
|
b, depthSwizzleTable, depthBufAddress, depthBufWidth, screenPos);
|
|
|
|
break;
|
|
|
|
case CGSHandler::PSMZ16:
|
|
|
|
case CGSHandler::PSMZ16S:
|
|
|
|
//TODO: Use real swizzle table
|
|
|
|
depthAddress = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMZ16>(
|
|
|
|
b, depthSwizzleTable, depthBufAddress, depthBufWidth, screenPos);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-06-28 16:35:44 -04:00
|
|
|
//Prevent writing out of bounds (seems to cause wierd issues
|
|
|
|
//on Intel GPUs with games such as SNK vs. Capcom: SVC Chaos)
|
|
|
|
fbAddress = fbAddress & NewInt(b, CGSHandler::RAMSIZE - 1);
|
|
|
|
depthAddress = depthAddress & NewInt(b, CGSHandler::RAMSIZE - 1);
|
|
|
|
|
2021-06-22 14:04:39 -04:00
|
|
|
switch(caps.framebufferFormat)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
case CGSHandler::PSMCT32:
|
|
|
|
{
|
|
|
|
dstPixel = CMemoryUtils::Memory_Read32(b, memoryBuffer, fbAddress);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CGSHandler::PSMCT24:
|
|
|
|
{
|
|
|
|
dstPixel = CMemoryUtils::Memory_Read24(b, memoryBuffer, fbAddress);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CGSHandler::PSMCT16:
|
|
|
|
case CGSHandler::PSMCT16S:
|
|
|
|
{
|
|
|
|
dstPixel = CMemoryUtils::Memory_Read16(b, memoryBuffer, fbAddress);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-09-18 11:56:54 -04:00
|
|
|
dstDepth = CDrawUtils::GetDepth(b, caps.depthbufferFormat, depthAddress, memoryBuffer);
|
2021-06-22 14:04:39 -04:00
|
|
|
|
2021-08-15 14:22:45 -04:00
|
|
|
outputColor = dstPixel->x();
|
2021-07-13 09:08:19 -04:00
|
|
|
outputDepth = dstDepth->x();
|
2021-06-20 15:13:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Framework::CMemStream shaderStream;
|
|
|
|
Nuanceur::CSpirvShaderGenerator::Generate(shaderStream, b, Nuanceur::CSpirvShaderGenerator::SHADER_TYPE_FRAGMENT);
|
|
|
|
shaderStream.Seek(0, Framework::STREAM_SEEK_SET);
|
|
|
|
return Framework::Vulkan::CShaderModule(m_context->device, shaderStream);
|
|
|
|
}
|
|
|
|
|
2021-07-19 12:59:36 -04:00
|
|
|
Framework::Vulkan::CShaderModule CDrawMobile::CreateStoreFragmentShader(const PIPELINE_CAPS& caps)
|
2021-06-21 17:33:19 -04:00
|
|
|
{
|
|
|
|
using namespace Nuanceur;
|
|
|
|
|
|
|
|
auto b = CShaderBuilder();
|
|
|
|
|
|
|
|
{
|
|
|
|
//Inputs
|
|
|
|
auto inputPosition = CFloat4Lvalue(b.CreateInput(Nuanceur::SEMANTIC_SYSTEM_POSITION));
|
|
|
|
|
|
|
|
//Outputs
|
2021-08-15 14:22:45 -04:00
|
|
|
auto outputColor = CUintLvalue(b.CreateOutputUint(Nuanceur::SEMANTIC_SYSTEM_COLOR, 0));
|
2021-07-13 09:08:19 -04:00
|
|
|
auto outputDepth = CUintLvalue(b.CreateOutputUint(Nuanceur::SEMANTIC_SYSTEM_COLOR, 1));
|
2021-06-21 17:33:19 -04:00
|
|
|
|
|
|
|
auto memoryBuffer = CArrayUintValue(b.CreateUniformArrayUint("memoryBuffer", DESCRIPTOR_LOCATION_BUFFER_MEMORY, Nuanceur::SYMBOL_ATTRIBUTE_COHERENT));
|
|
|
|
auto fbSwizzleTable = CImageUint2DValue(b.CreateImage2DUint(DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_FB));
|
|
|
|
auto depthSwizzleTable = CImageUint2DValue(b.CreateImage2DUint(DESCRIPTOR_LOCATION_IMAGE_SWIZZLETABLE_DEPTH));
|
2021-08-15 14:22:45 -04:00
|
|
|
auto subpassColorInput = CSubpassInputUintValue(b.CreateSubpassInputUint(DESCRIPTOR_LOCATION_IMAGE_INPUT_COLOR, 0));
|
2021-07-13 09:08:19 -04:00
|
|
|
auto subpassDepthInput = CSubpassInputUintValue(b.CreateSubpassInputUint(DESCRIPTOR_LOCATION_IMAGE_INPUT_DEPTH, 1));
|
2021-06-21 17:33:19 -04:00
|
|
|
|
|
|
|
//Push constants
|
|
|
|
auto fbDepthParams = CInt4Lvalue(b.CreateUniformInt4("fbDepthParams", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
2021-07-25 20:56:08 -04:00
|
|
|
auto texParams0 = CInt4Lvalue(b.CreateUniformInt4("texParams0", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
|
|
|
auto texParams1 = CInt4Lvalue(b.CreateUniformInt4("texParams1", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
|
|
|
auto texParams2 = CInt4Lvalue(b.CreateUniformInt4("texParams2", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
|
|
|
auto alphaFbParams = CInt4Lvalue(b.CreateUniformInt4("alphaFbParams", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
|
|
|
auto fogColor = CFloat4Lvalue(b.CreateUniformFloat4("fogColor", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
2021-06-21 17:33:19 -04:00
|
|
|
|
|
|
|
auto fbBufAddress = fbDepthParams->x();
|
|
|
|
auto fbBufWidth = fbDepthParams->y();
|
|
|
|
auto depthBufAddress = fbDepthParams->z();
|
|
|
|
auto depthBufWidth = fbDepthParams->w();
|
|
|
|
|
2021-07-25 20:56:08 -04:00
|
|
|
auto dstPixel = CUintLvalue(b.CreateVariableUint("dstPixel"));
|
2021-08-15 14:22:45 -04:00
|
|
|
auto dstDepth = CUintLvalue(b.CreateVariableUint("dstDepth"));
|
2021-09-10 16:06:20 -04:00
|
|
|
|
2021-08-15 14:22:45 -04:00
|
|
|
dstPixel = Load(subpassColorInput, NewInt2(b, 0, 0))->x();
|
|
|
|
dstDepth = Load(subpassDepthInput, NewInt2(b, 0, 0))->x();
|
2021-06-21 17:33:19 -04:00
|
|
|
|
|
|
|
auto fbAddress = CIntLvalue(b.CreateTemporaryInt());
|
|
|
|
auto depthAddress = CIntLvalue(b.CreateTemporaryInt());
|
|
|
|
|
|
|
|
auto screenPos = ToInt(inputPosition->xy());
|
|
|
|
|
|
|
|
switch(caps.framebufferFormat)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
case CGSHandler::PSMCT32:
|
|
|
|
case CGSHandler::PSMCT24:
|
|
|
|
case CGSHandler::PSMZ24:
|
|
|
|
fbAddress = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMCT32>(
|
|
|
|
b, fbSwizzleTable, fbBufAddress, fbBufWidth, screenPos);
|
|
|
|
break;
|
|
|
|
case CGSHandler::PSMCT16:
|
|
|
|
case CGSHandler::PSMCT16S:
|
|
|
|
fbAddress = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMCT16>(
|
|
|
|
b, fbSwizzleTable, fbBufAddress, fbBufWidth, screenPos);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(caps.depthbufferFormat)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
case CGSHandler::PSMZ32:
|
|
|
|
case CGSHandler::PSMZ24:
|
|
|
|
depthAddress = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMZ32>(
|
|
|
|
b, depthSwizzleTable, depthBufAddress, depthBufWidth, screenPos);
|
|
|
|
break;
|
|
|
|
case CGSHandler::PSMZ16:
|
|
|
|
case CGSHandler::PSMZ16S:
|
|
|
|
//TODO: Use real swizzle table
|
|
|
|
depthAddress = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMZ16>(
|
|
|
|
b, depthSwizzleTable, depthBufAddress, depthBufWidth, screenPos);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Prevent writing out of bounds (seems to cause wierd issues
|
|
|
|
//on Intel GPUs with games such as SNK vs. Capcom: SVC Chaos)
|
|
|
|
fbAddress = fbAddress & NewInt(b, CGSHandler::RAMSIZE - 1);
|
|
|
|
depthAddress = depthAddress & NewInt(b, CGSHandler::RAMSIZE - 1);
|
|
|
|
|
2021-09-18 11:56:54 -04:00
|
|
|
CDrawUtils::WriteToFramebuffer(b, caps.framebufferFormat, memoryBuffer, fbAddress, dstPixel);
|
2021-07-25 20:56:08 -04:00
|
|
|
if(caps.writeDepth)
|
|
|
|
{
|
2021-09-18 11:56:54 -04:00
|
|
|
CDrawUtils::WriteToDepthbuffer(b, caps.depthbufferFormat, memoryBuffer, depthAddress, dstDepth);
|
2021-07-25 20:56:08 -04:00
|
|
|
}
|
2021-06-21 17:33:19 -04:00
|
|
|
|
2021-08-15 14:22:45 -04:00
|
|
|
outputColor = dstPixel->x();
|
2021-06-21 17:33:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Framework::CMemStream shaderStream;
|
|
|
|
Nuanceur::CSpirvShaderGenerator::Generate(shaderStream, b, Nuanceur::CSpirvShaderGenerator::SHADER_TYPE_FRAGMENT);
|
|
|
|
shaderStream.Seek(0, Framework::STREAM_SEEK_SET);
|
|
|
|
return Framework::Vulkan::CShaderModule(m_context->device, shaderStream);
|
|
|
|
}
|
|
|
|
|
2021-06-23 08:12:07 -04:00
|
|
|
void CDrawMobile::CreateDrawImages()
|
2021-06-20 15:13:21 -04:00
|
|
|
{
|
2021-06-23 08:12:07 -04:00
|
|
|
m_drawColorImage = Framework::Vulkan::CImage(m_context->device, m_context->physicalDeviceMemoryProperties,
|
2021-06-23 20:27:14 -04:00
|
|
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
|
2021-09-10 16:06:20 -04:00
|
|
|
VK_FORMAT_R32_UINT, DRAW_AREA_SIZE, DRAW_AREA_SIZE, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
2021-06-23 08:12:07 -04:00
|
|
|
|
|
|
|
m_drawColorImage.SetLayout(m_context->queue, m_context->commandBufferPool,
|
2021-07-15 12:42:35 -04:00
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
|
2021-06-20 15:13:21 -04:00
|
|
|
|
2021-07-15 12:42:35 -04:00
|
|
|
m_drawColorImageView = m_drawColorImage.CreateImageView();
|
2021-06-20 15:13:21 -04:00
|
|
|
|
2021-06-23 08:12:07 -04:00
|
|
|
m_drawDepthImage = Framework::Vulkan::CImage(m_context->device, m_context->physicalDeviceMemoryProperties,
|
2021-07-13 09:08:19 -04:00
|
|
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
|
|
|
|
VK_FORMAT_R32_UINT, DRAW_AREA_SIZE, DRAW_AREA_SIZE, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
2021-06-20 15:13:21 -04:00
|
|
|
|
2021-06-23 08:12:07 -04:00
|
|
|
m_drawDepthImage.SetLayout(m_context->queue, m_context->commandBufferPool,
|
2021-07-15 12:42:35 -04:00
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
|
2021-06-23 20:27:14 -04:00
|
|
|
|
2021-07-15 12:42:35 -04:00
|
|
|
m_drawDepthImageView = m_drawDepthImage.CreateImageView();
|
2021-06-20 15:13:21 -04:00
|
|
|
}
|