Vulkan: Don't try to overlap proj with proj_through, will need a different approach.

Also, assorted bugfixes.
This commit is contained in:
Henrik Rydgard 2016-01-24 17:30:26 +01:00
parent 5f71b5b3ec
commit 1677697735
9 changed files with 28 additions and 17 deletions

View File

@ -494,6 +494,8 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
uint32_t vbOffset = 0;
if (useHWTransform) {
// We don't detect clears in this path, so here we can switch framebuffers if necessary.
int vertexCount = 0;
int maxIndex = 0;
bool useElements = true;
@ -529,7 +531,7 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
vkCmdSetBlendConstants(cmd_, bc);
shaderManager_->UpdateUniforms();
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform);
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, pipelineKey, dec_, vshader->GetModule(), fshader->GetModule(), true);
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, pipelineKey, dec_, vshader, fshader, true);
vkCmdBindPipeline(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline); // TODO: Avoid if same as last draw.
if (pipeline->uniformBlocks & UB_VS_FS_BASE) {
@ -548,11 +550,11 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
};
vkCmdBindDescriptorSets(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 0, 1, &ds, 3, dynamicUBOOffsets);
vbOffset = (uint32_t)frame->pushData->Push(decoded, vertexCount * dec_->GetDecVtxFmt().stride);
vbOffset = (uint32_t)frame->pushData->PushAligned(decoded, vertexCount * dec_->GetDecVtxFmt().stride, 16);
VkDeviceSize offsets[1] = { vbOffset };
if (useElements) {
ibOffset = (uint32_t)frame->pushData->Push(decIndex, 2 * indexGen.VertexCount());
ibOffset = (uint32_t)frame->pushData->PushAligned(decIndex, 2 * indexGen.VertexCount(), 16);
// TODO: Avoid rebinding vertex/index buffers if the vertex size stays the same by using the offset arguments
// Might want to separate vertices out into a different push buffer in that case.
vkCmdBindVertexBuffers(cmd_, 0, 1, buf, offsets);
@ -591,6 +593,9 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
dec_->VertexType(), inds, GE_VTYPE_IDX_16BIT, dec_->GetDecVtxFmt(),
maxIndex, framebufferManager_, textureCache_, transformed, transformedExpanded, drawBuffer, numTrans, drawIndexed, &result, 1.0f);
// Only here, where we know whether to clear or to draw primitives, should we actually set the current framebuffer! Because that gives use the opportunity
// to use a "pre-clear" render pass, for high efficiency on tilers.
if (result.action == SW_DRAW_PRIMITIVES) {
VulkanPipelineRasterStateKey pipelineKey;
VulkanDynamicState dynState;
@ -614,7 +619,7 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
vkCmdSetBlendConstants(cmd_, bc);
shaderManager_->UpdateUniforms();
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform);
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, pipelineKey, dec_, vshader->GetModule(), fshader->GetModule(), false);
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, pipelineKey, dec_, vshader, fshader, false);
vkCmdBindPipeline(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline); // TODO: Avoid if same as last draw.
if (pipeline->uniformBlocks & UB_VS_FS_BASE) {

View File

@ -320,7 +320,7 @@ static const CommandTableEntry commandTable[] = {
{ GE_CMD_BOUNDINGBOX, FLAG_EXECUTE, 0, &GPU_Vulkan::Execute_BoundingBox }, // + FLUSHBEFORE when we implement... or not, do we need to?
// Changing the vertex type requires us to flush.
{ GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, DIRTY_PROJMATRIX, &GPU_Vulkan::Execute_VertexType },
{ GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPU_Vulkan::Execute_VertexType },
{ GE_CMD_BEZIER, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPU_Vulkan::Execute_Bezier },
{ GE_CMD_SPLINE, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPU_Vulkan::Execute_Spline },

View File

@ -4,6 +4,7 @@
#include "Common/StringUtils.h"
#include "GPU/Vulkan/VulkanUtil.h"
#include "GPU/Vulkan/PipelineManagerVulkan.h"
#include "GPU/Vulkan/ShaderManagerVulkan.h"
// #include "GPU/Vulkan/"
#include "thin3d/VulkanContext.h"
@ -285,12 +286,12 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
return vulkanPipeline;
}
VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layout, const VulkanPipelineRasterStateKey &rasterKey, const VertexDecoder *vtxDec, VkShaderModule vShader, VkShaderModule fShader, bool useHwTransform) {
VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layout, const VulkanPipelineRasterStateKey &rasterKey, const VertexDecoder *vtxDec, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform) {
VulkanPipelineKey key;
key.raster = rasterKey;
key.useHWTransform = useHwTransform;
key.vShader = vShader;
key.fShader = fShader;
key.vShader = vs->GetModule();
key.fShader = fs->GetModule();
key.vtxDec = vtxDec;
auto iter = pipelines_.find(key);
if (iter != pipelines_.end()) {
@ -299,7 +300,7 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layo
VulkanPipeline *pipeline = CreateVulkanPipeline(
vulkan_->GetDevice(), pipelineCache_, layout, vulkan_->GetSurfaceRenderPass(),
rasterKey, vtxDec, vShader, fShader, useHwTransform);
rasterKey, vtxDec, key.vShader, key.fShader, useHwTransform);
pipelines_[key] = pipeline;
return pipeline;
}

View File

@ -74,13 +74,15 @@ struct VulkanPipeline {
};
class VulkanContext;
class VulkanVertexShader;
class VulkanFragmentShader;
class PipelineManagerVulkan {
public:
PipelineManagerVulkan(VulkanContext *ctx);
~PipelineManagerVulkan();
VulkanPipeline *GetOrCreatePipeline(VkPipelineLayout layout, const VulkanPipelineRasterStateKey &rasterKey, const VertexDecoder *vtxDec, VkShaderModule vShader, VkShaderModule fShader, bool useHwTransform);
VulkanPipeline *GetOrCreatePipeline(VkPipelineLayout layout, const VulkanPipelineRasterStateKey &rasterKey, const VertexDecoder *vtxDec, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform);
int GetNumPipelines() const { return (int)pipelines_.size(); }
void Clear();

View File

@ -249,7 +249,7 @@ void ShaderManagerVulkan::BaseUpdateUniforms(int dirtyUniforms) {
Matrix4x4 proj_through;
proj_through.setOrtho(0.0f, gstate_c.curRTWidth, 0, gstate_c.curRTHeight, 0, 1);
ConvertProjMatrixToVulkanThrough(proj_through);
CopyMatrix4x4(ub_base.proj, proj_through.getReadPtr());
CopyMatrix4x4(ub_base.proj_through, proj_through.getReadPtr());
} else {
Matrix4x4 flippedMatrix;
memcpy(&flippedMatrix, gstate.projMatrix, 16 * sizeof(float));

View File

@ -34,7 +34,7 @@ void ConvertProjMatrixToVulkan(Matrix4x4 & in);
// Pretty much full. Will need more bits for more fine grained dirty tracking for lights.
enum {
DIRTY_PROJMATRIX = (1 << 0),
// 1 << 1 is free
DIRTY_PROJTHROUGHMATRIX = (1 << 1),
DIRTY_FOGCOLOR = (1 << 2),
DIRTY_FOGCOEF = (1 << 3),
DIRTY_TEXENV = (1 << 4),
@ -82,8 +82,10 @@ enum {
DIRTY_ALL = 0xFFFFFFFF
};
// TODO: Split into two structs, one for software transform and one for hardware transform, to save space.
struct UB_VS_FS_Base {
float proj[16];
float proj_through[16];
float view[16];
float world[16];
float tex[16]; // not that common, may want to break out
@ -104,7 +106,8 @@ struct UB_VS_FS_Base {
};
static const char *ub_baseStr =
R"( mat4 proj_mtx;
R"( mat4 proj_mtx;
mat4 proj_through_mtx;
mat4 view_mtx;
mat4 world_mtx;
mat4 tex_mtx;

View File

@ -172,13 +172,13 @@ void ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManager, ShaderManagerV
key.depthCompareOp = VK_COMPARE_OP_ALWAYS;
key.depthWriteEnable = gstate.isClearModeDepthMask();
if (gstate.isClearModeDepthMask()) {
// framebufferManager_->SetDepthUpdated();
fbManager.SetDepthUpdated();
}
// Color Test
bool colorMask = gstate.isClearModeColorMask();
bool alphaMask = gstate.isClearModeAlphaMask();
key.colorWriteMask = (colorMask ? (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_A_BIT) : 0) | (alphaMask ? VK_COLOR_COMPONENT_A_BIT : 0);
key.colorWriteMask = (colorMask ? (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT) : 0) | (alphaMask ? VK_COLOR_COMPONENT_A_BIT : 0);
GenericStencilFuncState stencilState;
ConvertStencilFuncState(stencilState);

View File

@ -34,7 +34,7 @@ struct VulkanPipelineRasterStateKey {
unsigned int blendOpAlpha : 3; // VkBlendOp
bool logicOpEnable : 1;
unsigned int logicOp : 4; // VkLogicOp
int colorWriteMask : 4;
unsigned int colorWriteMask : 4;
// Depth/Stencil
bool depthTestEnable : 1;

View File

@ -242,7 +242,7 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer) {
WRITE(p, " v_fogdepth = position.w;\n");
}
if (isModeThrough) {
WRITE(p, " gl_Position = base.proj_mtx * vec4(position.xyz, 1.0);\n");
WRITE(p, " gl_Position = base.proj_through_mtx * vec4(position.xyz, 1.0);\n");
} else {
// The viewport is used in this case, so need to compensate for that.
if (gstate_c.Supports(GPU_ROUND_DEPTH_TO_16BIT)) {