mirror of
https://github.com/libretro/ppsspp.git
synced 2025-02-26 11:45:26 +00:00
Buffered rendering is starting to work, though still kinda broken.
This commit is contained in:
parent
2b93338255
commit
0c70735bc4
@ -1307,6 +1307,9 @@ void TransitionImageLayout(VkCommandBuffer cmd, VkImage image, VkImageAspectFlag
|
||||
if (old_image_layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
|
||||
image_memory_barrier.srcAccessMask |= VK_ACCESS_MEMORY_READ_BIT;
|
||||
}
|
||||
if (old_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
|
||||
image_memory_barrier.srcAccessMask |= VK_ACCESS_SHADER_READ_BIT;
|
||||
}
|
||||
|
||||
if (old_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
|
||||
image_memory_barrier.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
|
@ -362,6 +362,14 @@ void VulkanTexture::EndCreate() {
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
||||
void VulkanTexture::TransitionForUpload() {
|
||||
VkCommandBuffer cmd = vulkan_->GetInitCommandBuffer();
|
||||
TransitionImageLayout(cmd, image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
}
|
||||
|
||||
void VulkanTexture::Destroy() {
|
||||
if (view != VK_NULL_HANDLE) {
|
||||
vulkan_->Delete().QueueDeleteImageView(view);
|
||||
|
@ -34,6 +34,9 @@ public:
|
||||
bool CreateDirect(int w, int h, int numMips, VkFormat format, VkImageLayout initialLayout, VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, const VkComponentMapping *mapping = nullptr);
|
||||
void UploadMip(int mip, int mipWidth, int mipHeight, VkBuffer buffer, uint32_t offset, size_t rowLength); // rowLength is in pixels
|
||||
void EndCreate();
|
||||
|
||||
void TransitionForUpload();
|
||||
|
||||
int GetNumMips() const { return numMips_; }
|
||||
void Destroy();
|
||||
|
||||
|
@ -704,6 +704,7 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int
|
||||
if (useBufferedRendering_ && vfb && vfb->fbo) {
|
||||
draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP });
|
||||
SetViewport2D(0, 0, vfb->renderWidth, vfb->renderHeight);
|
||||
draw_->SetScissorRect(0, 0, vfb->renderWidth, vfb->renderHeight);
|
||||
} else {
|
||||
// We are drawing to the back buffer so need to flip.
|
||||
if (needBackBufferYSwap_)
|
||||
@ -711,6 +712,7 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int
|
||||
float x, y, w, h;
|
||||
CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)pixelWidth_, (float)pixelHeight_, ROTATION_LOCKED_HORIZONTAL);
|
||||
SetViewport2D(x, y, w, h);
|
||||
draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_);
|
||||
}
|
||||
DisableState();
|
||||
|
||||
@ -894,6 +896,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() {
|
||||
}
|
||||
// Just a pointer to plain memory to draw. We should create a framebuffer, then draw to it.
|
||||
SetViewport2D(0, 0, pixelWidth_, pixelHeight_);
|
||||
draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_);
|
||||
DrawFramebufferToOutput(Memory::GetPointer(displayFramebufPtr_), displayFormat_, displayStride_, true);
|
||||
return;
|
||||
}
|
||||
@ -942,6 +945,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() {
|
||||
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR });
|
||||
draw_->BindFramebufferAsTexture(vfb->fbo, 0, Draw::FB_COLOR_BIT, 0);
|
||||
SetViewport2D(0, 0, pixelWidth_, pixelHeight_);
|
||||
draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_);
|
||||
bool linearFilter = g_Config.iBufFilter == SCALE_LINEAR;
|
||||
// We are doing the DrawActiveTexture call directly to the backbuffer here. Hence, we must
|
||||
// flip V.
|
||||
@ -967,6 +971,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() {
|
||||
int fbo_w, fbo_h;
|
||||
draw_->GetFramebufferDimensions(extraFBOs_[0], &fbo_w, &fbo_h);
|
||||
SetViewport2D(0, 0, fbo_w, fbo_h);
|
||||
draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_);
|
||||
shaderManager_->DirtyLastShader(); // dirty lastShader_
|
||||
PostShaderUniforms uniforms{};
|
||||
CalculatePostShaderUniforms(vfb->bufferWidth, vfb->bufferHeight, renderWidth_, renderHeight_, &uniforms);
|
||||
@ -1013,6 +1018,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() {
|
||||
}*/
|
||||
} else {
|
||||
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR });
|
||||
draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_);
|
||||
// We are doing the DrawActiveTexture call directly to the backbuffer here. Hence, we must
|
||||
// flip V.
|
||||
if (needBackBufferYSwap_)
|
||||
|
@ -68,7 +68,6 @@ DrawEngineVulkan::DrawEngineVulkan(VulkanContext *vulkan, Draw::DrawContext *dra
|
||||
: vulkan_(vulkan),
|
||||
draw_(draw),
|
||||
prevPrim_(GE_PRIM_INVALID),
|
||||
lastVTypeID_(-1),
|
||||
numDrawCalls(0),
|
||||
vertexCountInDrawCalls(0),
|
||||
curFrame_(0),
|
||||
@ -329,10 +328,12 @@ inline void DrawEngineVulkan::SetupVertexDecoderInternal(u32 vertType) {
|
||||
const u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24);
|
||||
|
||||
// If vtype has changed, setup the vertex decoder.
|
||||
if (vertTypeID != lastVTypeID_) {
|
||||
if (vertTypeID != lastVType_) {
|
||||
dec_ = GetVertexDecoder(vertTypeID);
|
||||
lastVTypeID_ = vertTypeID;
|
||||
lastVType_ = vertTypeID;
|
||||
}
|
||||
if (!dec_)
|
||||
Crash();
|
||||
}
|
||||
|
||||
void DrawEngineVulkan::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) {
|
||||
@ -710,7 +711,7 @@ void DrawEngineVulkan::DoFlush() {
|
||||
}
|
||||
prim = indexGen.Prim();
|
||||
|
||||
bool hasColor = (lastVTypeID_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
|
||||
bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
|
||||
if (gstate.isModeThrough()) {
|
||||
gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && (hasColor || gstate.getMaterialAmbientA() == 255);
|
||||
} else {
|
||||
@ -743,7 +744,7 @@ void DrawEngineVulkan::DoFlush() {
|
||||
|
||||
dirtyUniforms_ |= shaderManager_->UpdateUniforms();
|
||||
|
||||
shaderManager_->GetShaders(prim, lastVTypeID_, &vshader, &fshader, useHWTransform);
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform);
|
||||
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, renderPass, pipelineKey_, dec_, vshader, fshader, true);
|
||||
if (!pipeline) {
|
||||
// Already logged, let's bail out.
|
||||
@ -778,7 +779,7 @@ void DrawEngineVulkan::DoFlush() {
|
||||
} else {
|
||||
// Decode to "decoded"
|
||||
DecodeVerts(nullptr, nullptr, nullptr);
|
||||
bool hasColor = (lastVTypeID_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
|
||||
bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
|
||||
if (gstate.isModeThrough()) {
|
||||
gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && (hasColor || gstate.getMaterialAmbientA() == 255);
|
||||
} else {
|
||||
@ -849,7 +850,7 @@ void DrawEngineVulkan::DoFlush() {
|
||||
|
||||
dirtyUniforms_ |= shaderManager_->UpdateUniforms();
|
||||
|
||||
shaderManager_->GetShaders(prim, lastVTypeID_, &vshader, &fshader, useHWTransform);
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform);
|
||||
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, renderPass, pipelineKey, dec_, vshader, fshader, false);
|
||||
if (!pipeline) {
|
||||
// Already logged, let's bail out.
|
||||
|
@ -197,8 +197,6 @@ private:
|
||||
IndexGenerator indexGen;
|
||||
GEPrimitiveType prevPrim_;
|
||||
|
||||
u32 lastVTypeID_;
|
||||
|
||||
TransformedVertex *transformed = nullptr;
|
||||
TransformedVertex *transformedExpanded = nullptr;
|
||||
|
||||
|
@ -129,9 +129,9 @@ void FramebufferManagerVulkan::InitDeviceObjects() {
|
||||
assert(fsBasicTex_ != VK_NULL_HANDLE);
|
||||
assert(vsBasicTex_ != VK_NULL_HANDLE);
|
||||
|
||||
// Get a representative render pass and use when creating the pipeline.
|
||||
pipelineBasicTexBackBuffer_ = vulkan2D_.GetPipeline(pipelineCache2D_, vulkan_->GetSurfaceRenderPass(), vsBasicTex_, fsBasicTex_);
|
||||
pipelineBasicTexFrameBuffer_ = vulkan2D_.GetPipeline(pipelineCache2D_, (VkRenderPass)draw_->GetNativeObject(Draw::NativeObject::COMPATIBLE_RENDERPASS), vsBasicTex_, fsBasicTex_);
|
||||
// Prime the 2D pipeline cache.
|
||||
vulkan2D_.GetPipeline(pipelineCache2D_, vulkan_->GetSurfaceRenderPass(), vsBasicTex_, fsBasicTex_);
|
||||
vulkan2D_.GetPipeline(pipelineCache2D_, (VkRenderPass)draw_->GetNativeObject(Draw::NativeObject::COMPATIBLE_RENDERPASS), vsBasicTex_, fsBasicTex_);
|
||||
|
||||
VkSamplerCreateInfo samp = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
|
||||
samp.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
@ -240,6 +240,8 @@ void FramebufferManagerVulkan::MakePixelTexture(const u8 *srcPixels, GEBufferFor
|
||||
drawPixelsTex_->CreateDirect(width, height, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
// Initialize backbuffer texture for DrawPixels
|
||||
drawPixelsTexFormat_ = srcPixelFormat;
|
||||
} else {
|
||||
drawPixelsTex_->TransitionForUpload();
|
||||
}
|
||||
|
||||
// TODO: We can just change the texture format and flip some bits around instead of this.
|
||||
@ -314,11 +316,6 @@ void FramebufferManagerVulkan::SetViewport2D(int x, int y, int w, int h) {
|
||||
}
|
||||
|
||||
void FramebufferManagerVulkan::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, bool linearFilter) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
// x, y, w, h are relative coordinates against destW/destH, which is not very intuitive.
|
||||
void FramebufferManagerVulkan::DrawTexture(VulkanTexture *texture, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, VkPipeline pipeline, int uvRotation) {
|
||||
float texCoords[8] = {
|
||||
u0,v0,
|
||||
u1,v0,
|
||||
@ -354,13 +351,18 @@ void FramebufferManagerVulkan::DrawTexture(VulkanTexture *texture, float x, floa
|
||||
vtx[i].y = vtx[i].y * invDestH - 1.0f;
|
||||
}
|
||||
|
||||
draw_->FlushState();
|
||||
|
||||
// TODO: Should probably use draw_ directly and not go low level
|
||||
|
||||
VulkanPushBuffer *push = frameData_[curFrame_].push_;
|
||||
|
||||
VkCommandBuffer cmd = (VkCommandBuffer)draw_->GetNativeObject(Draw::NativeObject::RENDERPASS_COMMANDBUFFER);
|
||||
|
||||
// TODO: Choose linear or nearest appropriately, see GL impl.
|
||||
vulkan2D_.BindDescriptorSet(cmd, texture->GetImageView(), linearSampler_);
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
VkImageView view = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE_IMAGEVIEW);
|
||||
vulkan2D_.BindDescriptorSet(cmd, view, linearFilter ? linearSampler_ : nearestSampler_);
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, cur2DPipeline_);
|
||||
VkBuffer vbuffer;
|
||||
VkDeviceSize offset = push->Push(vtx, sizeof(vtx), &vbuffer);
|
||||
vkCmdBindVertexBuffers(cmd, 0, 1, &vbuffer, &offset);
|
||||
@ -368,7 +370,8 @@ void FramebufferManagerVulkan::DrawTexture(VulkanTexture *texture, float x, floa
|
||||
}
|
||||
|
||||
void FramebufferManagerVulkan::Bind2DShader() {
|
||||
|
||||
VkRenderPass rp = (VkRenderPass)draw_->GetNativeObject(Draw::NativeObject::COMPATIBLE_RENDERPASS);
|
||||
cur2DPipeline_ = vulkan2D_.GetPipeline(pipelineCache2D_, rp, vsBasicTex_, fsBasicTex_);
|
||||
}
|
||||
|
||||
void FramebufferManagerVulkan::BindPostShader(const PostShaderUniforms &uniforms) {
|
||||
|
@ -69,9 +69,7 @@ public:
|
||||
drawEngine_ = td;
|
||||
}
|
||||
|
||||
// If texture != 0, will bind it.
|
||||
// x,y,w,h are relative to destW, destH which fill out the target completely.
|
||||
void DrawTexture(VulkanTexture *texture, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, VkPipeline pipeline, int uvRotation);
|
||||
void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, bool linearFilter) override;
|
||||
|
||||
void DestroyAllFBOs();
|
||||
@ -188,6 +186,8 @@ private:
|
||||
VkPipeline pipelineBasicTexBackBuffer_;
|
||||
VkPipeline pipelineBasicTexFrameBuffer_;
|
||||
|
||||
VkPipeline cur2DPipeline_;
|
||||
|
||||
// Postprocessing
|
||||
VkPipeline pipelinePostShader_;
|
||||
|
||||
|
@ -217,6 +217,7 @@ VkPipeline Vulkan2D::GetPipeline(VkPipelineCache cache, VkRenderPass rp, VkShade
|
||||
PipelineKey key;
|
||||
key.vs = vs;
|
||||
key.fs = fs;
|
||||
key.rp = rp;
|
||||
|
||||
auto iter = pipelines_.find(key);
|
||||
if (iter != pipelines_.end()) {
|
||||
|
@ -132,6 +132,10 @@ static VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, VkDebugRep
|
||||
return false;
|
||||
if (msgCode == 11)
|
||||
return false;
|
||||
// Silence "invalid reads of buffer data" - usually just uninitialized color buffers that will immediately get cleared due to our
|
||||
// lacking clearing optimizations.
|
||||
if (msgCode == 15 && objType == VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT)
|
||||
return false;
|
||||
|
||||
#ifdef _WIN32
|
||||
std::string msg = message.str();
|
||||
@ -144,7 +148,7 @@ static VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, VkDebugRep
|
||||
MessageBoxA(NULL, message.str().c_str(), "Alert", MB_OK);
|
||||
}
|
||||
} else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
|
||||
if (options->breakOnWarning) {
|
||||
if (options->breakOnWarning && IsDebuggerPresent()) {
|
||||
DebugBreak();
|
||||
}
|
||||
}
|
||||
|
@ -677,6 +677,16 @@ public:
|
||||
|
||||
virtual void HandleEvent(Event ev, int width, int height, void *param1 = nullptr, void *param2 = nullptr) = 0;
|
||||
|
||||
// This flushes command buffers and waits for execution at the point of the end of the last
|
||||
// renderpass that wrote to the requested framebuffer. This is needed before trying to read it back
|
||||
// on modern APIs like Vulkan. Ifr the framebuffer is currently being rendered to, we'll just end the render pass.
|
||||
// The next draw call will automatically start up a new one.
|
||||
// APIs like OpenGL won't need to implement this one.
|
||||
virtual void WaitRenderCompletion(Framebuffer *fbo) {}
|
||||
|
||||
// Flush state like scissors etc so the caller can do its own custom drawing.
|
||||
virtual void FlushState() {}
|
||||
|
||||
protected:
|
||||
void CreatePresets();
|
||||
|
||||
|
@ -422,6 +422,11 @@ public:
|
||||
void BeginFrame() override;
|
||||
void EndFrame() override;
|
||||
|
||||
void FlushState() override {
|
||||
ApplyDynamicState();
|
||||
}
|
||||
void WaitRenderCompletion(Framebuffer *fbo) override;
|
||||
|
||||
std::string GetInfoString(InfoField info) const override {
|
||||
// TODO: Make these actually query the right information
|
||||
switch (info) {
|
||||
@ -447,15 +452,14 @@ public:
|
||||
switch (obj) {
|
||||
case NativeObject::COMPATIBLE_RENDERPASS:
|
||||
// Return a representative renderpass.
|
||||
return (uintptr_t)(curRenderPass_ == vulkan_->GetSurfaceRenderPass() ? curRenderPass_ : renderPasses_[0]);
|
||||
if (curRenderPass_ == vulkan_->GetSurfaceRenderPass())
|
||||
return (uintptr_t)curRenderPass_;
|
||||
else
|
||||
return (uintptr_t)renderPasses_[0];
|
||||
case NativeObject::RENDERPASS_COMMANDBUFFER:
|
||||
return (uintptr_t)cmd_;
|
||||
case NativeObject::BOUND_TEXTURE_IMAGEVIEW:
|
||||
if (boundTextures_[0]) {
|
||||
return (uintptr_t)boundTextures_[0]->GetImageView();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return (uintptr_t)boundImageView_[0];
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -508,11 +512,13 @@ private:
|
||||
};
|
||||
VKTexture *boundTextures_[MAX_BOUND_TEXTURES];
|
||||
VKSamplerState *boundSamplers_[MAX_BOUND_TEXTURES];
|
||||
VkImageView boundImageView_[MAX_BOUND_TEXTURES];
|
||||
|
||||
struct FrameData {
|
||||
VulkanPushBuffer *pushBuffer;
|
||||
VkCommandPool cmdPool_;
|
||||
VkCommandBuffer cmdBufs[MAX_FRAME_COMMAND_BUFFERS];
|
||||
int startCmdBufs_;
|
||||
int numCmdBufs_;
|
||||
|
||||
// Per-frame descriptor set cache. As it's per frame and reset every frame, we don't need to
|
||||
@ -863,17 +869,18 @@ VkCommandBuffer VKContext::AllocCmdBuf() {
|
||||
void VKContext::BeginFrame() {
|
||||
vulkan_->BeginFrame();
|
||||
|
||||
FrameData *frame = &frame_[frameNum_ & 1];
|
||||
frame->numCmdBufs_ = 0;
|
||||
vkResetCommandPool(vulkan_->GetDevice(), frame->cmdPool_, 0);
|
||||
push_ = frame->pushBuffer;
|
||||
FrameData &frame = frame_[frameNum_ & 1];
|
||||
frame.startCmdBufs_ = 0;
|
||||
frame.numCmdBufs_ = 0;
|
||||
vkResetCommandPool(vulkan_->GetDevice(), frame.cmdPool_, 0);
|
||||
push_ = frame.pushBuffer;
|
||||
|
||||
// OK, we now know that nothing is reading from this frame's data pushbuffer,
|
||||
push_->Reset();
|
||||
push_->Begin(vulkan_);
|
||||
|
||||
frame->descSets_.clear();
|
||||
VkResult result = vkResetDescriptorPool(device_, frame->descriptorPool, 0);
|
||||
frame.descSets_.clear();
|
||||
VkResult result = vkResetDescriptorPool(device_, frame.descriptorPool, 0);
|
||||
assert(result == VK_SUCCESS);
|
||||
|
||||
scissor_.extent.width = pixel_xres;
|
||||
@ -882,6 +889,10 @@ void VKContext::BeginFrame() {
|
||||
viewportDirty_ = true;
|
||||
}
|
||||
|
||||
void VKContext::WaitRenderCompletion(Framebuffer *fbo) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void VKContext::EndFrame() {
|
||||
if (curRenderPass_) {
|
||||
vulkan_->EndSurfaceRenderPass();
|
||||
@ -891,7 +902,7 @@ void VKContext::EndFrame() {
|
||||
|
||||
// Cap off and submit all the command buffers we recorded during the frame.
|
||||
FrameData &frame = frame_[frameNum_ & 1];
|
||||
for (int i = 0; i < frame.numCmdBufs_; i++) {
|
||||
for (int i = frame.startCmdBufs_; i < frame.numCmdBufs_; i++) {
|
||||
vkEndCommandBuffer(frame.cmdBufs[i]);
|
||||
vulkan_->QueueBeforeSurfaceRender(frame.cmdBufs[i]);
|
||||
}
|
||||
@ -1204,6 +1215,7 @@ void VKContext::UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset,
|
||||
void VKContext::BindTextures(int start, int count, Texture **textures) {
|
||||
for (int i = start; i < start + count; i++) {
|
||||
boundTextures_[i] = static_cast<VKTexture *>(textures[i]);
|
||||
boundImageView_[i] = boundTextures_[i]->GetImageView();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1719,6 +1731,7 @@ void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChanne
|
||||
// we're between passes so it's OK.
|
||||
vkCmdPipelineBarrier(transitionCmdBuf, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, 0, 0, 0, 1, &barrier);
|
||||
fb->color.layout = barrier.newLayout;
|
||||
boundImageView_[0] = fb->color.view;
|
||||
}
|
||||
|
||||
void VKContext::BindFramebufferForRead(Framebuffer *fbo) { /* noop */ }
|
||||
|
Loading…
x
Reference in New Issue
Block a user