|
|
|
|
@@ -95,149 +95,6 @@ static AlphaType getSrcAlphaType(jshort srctype) {
|
|
|
|
|
ALPHA_TYPE_PRE_MULTIPLIED : ALPHA_TYPE_STRAIGHT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void VKTexturePoolTexture_Dispose(VKDevice* device, void* ctx) {
|
|
|
|
|
VKTexturePoolHandle* hnd = (VKTexturePoolHandle*) ctx;
|
|
|
|
|
VKTexturePoolHandle_ReleaseTexture(hnd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void VKBlitSwToTextureViaPooledTexture(VKRenderingContext* context,
|
|
|
|
|
VKSDOps *dstOps,
|
|
|
|
|
const SurfaceDataRasInfo *srcInfo, jshort srctype, jint hint,
|
|
|
|
|
int dx1, int dy1, int dx2, int dy2) {
|
|
|
|
|
VKSDOps* surface = context->surface;
|
|
|
|
|
VKDevice* device = surface->device;
|
|
|
|
|
|
|
|
|
|
const int sw = srcInfo->bounds.x2 - srcInfo->bounds.x1;
|
|
|
|
|
const int sh = srcInfo->bounds.y2 - srcInfo->bounds.y1;
|
|
|
|
|
|
|
|
|
|
ARRAY(VKTxVertex) vertices = ARRAY_ALLOC(VKTxVertex, 4);
|
|
|
|
|
/*
|
|
|
|
|
* (p1)---------(p2)
|
|
|
|
|
* | |
|
|
|
|
|
* | |
|
|
|
|
|
* | |
|
|
|
|
|
* (p4)---------(p3)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
BlitSrcType type = decodeSrcType(device, srctype);
|
|
|
|
|
VKTexturePoolHandle* hnd = VKTexturePool_GetTexture(device->texturePool, sw, sh, type.format);
|
|
|
|
|
double u = (double)sw;
|
|
|
|
|
double v = (double)sh;
|
|
|
|
|
|
|
|
|
|
ARRAY_PUSH_BACK(vertices) = (VKTxVertex) {dx1, dy1, 0.0f, 0.0f};
|
|
|
|
|
ARRAY_PUSH_BACK(vertices) = (VKTxVertex) {dx2, dy1, u, 0.0f};
|
|
|
|
|
ARRAY_PUSH_BACK(vertices) = (VKTxVertex) {dx1, dy2, 0.0f, v};
|
|
|
|
|
ARRAY_PUSH_BACK(vertices) = (VKTxVertex) {dx2, dy2, u, v};
|
|
|
|
|
|
|
|
|
|
VKBuffer* renderVertexBuffer = ARRAY_TO_VERTEX_BUF(device, vertices);
|
|
|
|
|
ARRAY_FREE(vertices);
|
|
|
|
|
|
|
|
|
|
J2dTraceLn4(J2D_TRACE_VERBOSE, "replaceTextureRegion src (dw, dh) : [%d, %d] dest (dx1, dy1) =[%d, %d]",
|
|
|
|
|
(dx2 - dx1), (dy2 - dy1), dx1, dy1);
|
|
|
|
|
VKBuffer *buffer =
|
|
|
|
|
VKBuffer_CreateFromRaster(device, (VKBuffer_RasterInfo){
|
|
|
|
|
.data = srcInfo->rasBase,
|
|
|
|
|
.x1 = srcInfo->bounds.x1,
|
|
|
|
|
.y1 = srcInfo->bounds.y1,
|
|
|
|
|
.w = sw,
|
|
|
|
|
.h = sh,
|
|
|
|
|
.pixelStride = srcInfo->pixelStride,
|
|
|
|
|
.scanStride = srcInfo->scanStride
|
|
|
|
|
}, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_READ_BIT);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
VkImageMemoryBarrier barrier;
|
|
|
|
|
VKBarrierBatch barrierBatch = {};
|
|
|
|
|
VKImage_AddBarrier(&barrier, &barrierBatch, VKTexturePoolHandle_GetTexture(hnd),
|
|
|
|
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
|
|
|
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
|
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
|
|
|
|
VKRenderer_RecordBarriers(device->renderer, NULL, NULL, &barrier, &barrierBatch);
|
|
|
|
|
}
|
|
|
|
|
VKImage_LoadBuffer(context->surface->device,
|
|
|
|
|
VKTexturePoolHandle_GetTexture(hnd), buffer, 0, 0, sw, sh);
|
|
|
|
|
{
|
|
|
|
|
VkImageMemoryBarrier barrier;
|
|
|
|
|
VKBarrierBatch barrierBatch = {};
|
|
|
|
|
VKImage_AddBarrier(&barrier, &barrierBatch, VKTexturePoolHandle_GetTexture(hnd),
|
|
|
|
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
|
|
|
|
VK_ACCESS_SHADER_READ_BIT,
|
|
|
|
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
|
|
|
|
VKRenderer_RecordBarriers(device->renderer, NULL, NULL, &barrier, &barrierBatch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKImage* src = VKTexturePoolHandle_GetTexture(hnd);
|
|
|
|
|
VkDescriptorSet srcDescriptorSet = VKImage_GetDescriptorSet(device, src, type.format, type.swizzle);
|
|
|
|
|
VKRenderer_TextureRender(srcDescriptorSet, renderVertexBuffer->handle, 4, hint, SAMPLER_WRAP_BORDER);
|
|
|
|
|
|
|
|
|
|
VKRenderer_FlushSurface(dstOps);
|
|
|
|
|
VKRenderer_DisposeOnCleanup(device->renderer, VKTexturePoolTexture_Dispose, hnd);
|
|
|
|
|
VKRenderer_DisposeOnCleanup(device->renderer, VKBuffer_Dispose, buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static jboolean clipDestCoords(
|
|
|
|
|
VKRenderingContext* context,
|
|
|
|
|
jdouble *dx1, jdouble *dy1, jdouble *dx2, jdouble *dy2,
|
|
|
|
|
jint *sx1, jint *sy1, jint *sx2, jint *sy2,
|
|
|
|
|
jint destW, jint destH) {
|
|
|
|
|
// Trim destination rect by clip-rect (or dest.bounds)
|
|
|
|
|
const jint sw = *sx2 - *sx1;
|
|
|
|
|
const jint sh = *sy2 - *sy1;
|
|
|
|
|
const jdouble dw = *dx2 - *dx1;
|
|
|
|
|
const jdouble dh = *dy2 - *dy1;
|
|
|
|
|
VkRect2D* clipRect = &context->clipRect;
|
|
|
|
|
jdouble dcx1 = 0;
|
|
|
|
|
jdouble dcx2 = destW;
|
|
|
|
|
jdouble dcy1 = 0;
|
|
|
|
|
jdouble dcy2 = destH;
|
|
|
|
|
if (clipRect->offset.x > dcx1)
|
|
|
|
|
dcx1 = clipRect->offset.x;
|
|
|
|
|
const int maxX = clipRect->offset.x + clipRect->extent.width;
|
|
|
|
|
if (dcx2 > maxX)
|
|
|
|
|
dcx2 = maxX;
|
|
|
|
|
if (clipRect->offset.y > dcy1)
|
|
|
|
|
dcy1 = clipRect->offset.y;
|
|
|
|
|
const int maxY = clipRect->offset.y + clipRect->extent.height;
|
|
|
|
|
if (dcy2 > maxY)
|
|
|
|
|
dcy2 = maxY;
|
|
|
|
|
|
|
|
|
|
if (dcx1 >= dcx2) {
|
|
|
|
|
J2dTraceLn2(J2D_TRACE_ERROR, "\tclipDestCoords: dcx1=%1.2f, dcx2=%1.2f", dcx1, dcx2);
|
|
|
|
|
dcx1 = dcx2;
|
|
|
|
|
}
|
|
|
|
|
if (dcy1 >= dcy2) {
|
|
|
|
|
J2dTraceLn2(J2D_TRACE_ERROR, "\tclipDestCoords: dcy1=%1.2f, dcy2=%1.2f", dcy1, dcy2);
|
|
|
|
|
dcy1 = dcy2;
|
|
|
|
|
}
|
|
|
|
|
if (*dx2 <= dcx1 || *dx1 >= dcx2 || *dy2 <= dcy1 || *dy1 >= dcy2) {
|
|
|
|
|
J2dTraceLn(J2D_TRACE_INFO, "\tclipDestCoords: dest rect doesn't intersect clip area");
|
|
|
|
|
J2dTraceLn4(J2D_TRACE_INFO, "\tdx2=%1.4f <= dcx1=%1.4f || *dx1=%1.4f >= dcx2=%1.4f", *dx2, dcx1, *dx1, dcx2);
|
|
|
|
|
J2dTraceLn4(J2D_TRACE_INFO, "\t*dy2=%1.4f <= dcy1=%1.4f || *dy1=%1.4f >= dcy2=%1.4f", *dy2, dcy1, *dy1, dcy2);
|
|
|
|
|
return JNI_FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (*dx1 < dcx1) {
|
|
|
|
|
J2dTraceLn3(J2D_TRACE_VERBOSE, "\t\tdx1=%1.2f, will be clipped to %1.2f | sx1+=%d", *dx1, dcx1, (jint)((dcx1 - *dx1) * (sw/dw)));
|
|
|
|
|
*sx1 += (jint)((dcx1 - *dx1) * (sw/dw));
|
|
|
|
|
*dx1 = dcx1;
|
|
|
|
|
}
|
|
|
|
|
if (*dx2 > dcx2) {
|
|
|
|
|
J2dTraceLn3(J2D_TRACE_VERBOSE, "\t\tdx2=%1.2f, will be clipped to %1.2f | sx2-=%d", *dx2, dcx2, (jint)((*dx2 - dcx2) * (sw/dw)));
|
|
|
|
|
*sx2 -= (jint)((*dx2 - dcx2) * (sw/dw));
|
|
|
|
|
*dx2 = dcx2;
|
|
|
|
|
}
|
|
|
|
|
if (*dy1 < dcy1) {
|
|
|
|
|
J2dTraceLn3(J2D_TRACE_VERBOSE, "\t\tdy1=%1.2f, will be clipped to %1.2f | sy1+=%d", *dy1, dcy1, (jint)((dcy1 - *dy1) * (sh/dh)));
|
|
|
|
|
*sy1 += (jint)((dcy1 - *dy1) * (sh/dh));
|
|
|
|
|
*dy1 = dcy1;
|
|
|
|
|
}
|
|
|
|
|
if (*dy2 > dcy2) {
|
|
|
|
|
J2dTraceLn3(J2D_TRACE_VERBOSE, "\t\tdy2=%1.2f, will be clipped to %1.2f | sy2-=%d", *dy2, dcy2, (jint)((*dy2 - dcy2) * (sh/dh)));
|
|
|
|
|
*sy2 -= (jint)((*dy2 - dcy2) * (sh/dh));
|
|
|
|
|
*dy2 = dcy2;
|
|
|
|
|
}
|
|
|
|
|
return JNI_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VKBlitLoops_IsoBlit(VKSDOps* srcOps, jint filter,
|
|
|
|
|
jint sx1, jint sy1, jint sx2, jint sy2,
|
|
|
|
|
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
|
|
|
|
|
@@ -265,109 +122,134 @@ void VKBlitLoops_IsoBlit(VKSDOps* srcOps, jint filter,
|
|
|
|
|
VK_COMPONENT_SWIZZLE_ONE);
|
|
|
|
|
VKPackedSwizzle swizzle = srcOpaque ? OPAQUE_SWIZZLE : 0;
|
|
|
|
|
|
|
|
|
|
VKRenderer_DrawImage(srcOps->image, alphaType, srcOps->image->format, swizzle, filter, SAMPLER_WRAP_BORDER,
|
|
|
|
|
if (!VKRenderer_Validate(SHADER_BLIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) return;
|
|
|
|
|
VKRenderer_DrawImage(srcOps->image, srcOps->image->format, swizzle, filter, SAMPLER_WRAP_BORDER,
|
|
|
|
|
(float)sx1, (float)sy1, (float)sx2, (float)sy2, (float)dx1, (float)dy1, (float)dx2, (float)dy2);
|
|
|
|
|
VKRenderer_AddSurfaceDependency(srcOps, context->surface);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void VKBlitLoops_DisposeTexture(VKDevice* device, void* data) {
|
|
|
|
|
VKTexturePoolHandle_ReleaseTexture(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void VKBlitLoops_DisposeBuffer(VKDevice* device, void* data) {
|
|
|
|
|
device->vkDestroyBuffer(device->handle, (VkBuffer) data, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void VKBlitLoops_DisposeMemory(VKDevice* device, void* data) {
|
|
|
|
|
VKAllocator_Free(device->allocator, data);
|
|
|
|
|
}
|
|
|
|
|
static void VKBlitLoops_FindStageBufferMemoryType(VKMemoryRequirements* requirements) {
|
|
|
|
|
VKAllocator_FindMemoryType(requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
|
|
|
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
|
|
|
|
VKAllocator_FindMemoryType(requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_ALL_MEMORY_PROPERTIES);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VKBlitLoops_Blit(JNIEnv *env,
|
|
|
|
|
jlong pSrcOps, jboolean xform, jint hint,
|
|
|
|
|
jshort srctype,
|
|
|
|
|
SurfaceDataOps* src,
|
|
|
|
|
jshort srctype, jint hint,
|
|
|
|
|
jint sx1, jint sy1,
|
|
|
|
|
jint sx2, jint sy2,
|
|
|
|
|
jdouble dx1, jdouble dy1,
|
|
|
|
|
jdouble dx2, jdouble dy2)
|
|
|
|
|
{
|
|
|
|
|
J2dRlsTraceLn8(J2D_TRACE_VERBOSE, "VKRenderQueue_flushBuffer: BLIT_Blit (%d %d %d %d) -> (%f %f %f %f) ",
|
|
|
|
|
sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2)
|
|
|
|
|
J2dRlsTraceLn2(J2D_TRACE_VERBOSE, "VKRenderQueue_flushBuffer: BLIT_Blit xform=%d srctype=%d", xform, srctype)
|
|
|
|
|
|
|
|
|
|
SurfaceDataOps *srcOps = (SurfaceDataOps *)jlong_to_ptr(pSrcOps);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (srcOps == NULL) {
|
|
|
|
|
J2dRlsTraceLn1(J2D_TRACE_ERROR, "VKBlitLoops_Blit: srcOps(%p) is null",
|
|
|
|
|
srcOps)
|
|
|
|
|
if (src == NULL) {
|
|
|
|
|
J2dRlsTraceLn(J2D_TRACE_ERROR, "VKRenderer_Blit: src is null");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
VKRenderingContext* context = VKRenderer_GetContext();
|
|
|
|
|
|
|
|
|
|
if (!VKRenderer_Validate(SHADER_BLIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, getSrcAlphaType(srctype))) {
|
|
|
|
|
J2dTraceLn(J2D_TRACE_INFO, "VKBlitLoops_Blit: VKRenderer_Validate cannot validate renderer");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKRenderingContext *context = VKRenderer_GetContext();
|
|
|
|
|
VKSDOps *dstOps = context->surface;
|
|
|
|
|
const jint sw = sx2 - sx1;
|
|
|
|
|
const jint sh = sy2 - sy1;
|
|
|
|
|
const jint dw = dx2 - dx1;
|
|
|
|
|
const jint dh = dy2 - dy1;
|
|
|
|
|
|
|
|
|
|
if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0) {
|
|
|
|
|
J2dTraceLn(J2D_TRACE_ERROR, "MTLBlitLoops_Blit: invalid dimensions");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!xform) {
|
|
|
|
|
clipDestCoords(context,
|
|
|
|
|
&dx1, &dy1, &dx2, &dy2,
|
|
|
|
|
&sx1, &sy1, &sx2, &sy2,
|
|
|
|
|
dstOps->image->extent.width,dstOps->image->extent.height
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SurfaceDataRasInfo srcInfo;
|
|
|
|
|
srcInfo.bounds.x1 = sx1;
|
|
|
|
|
srcInfo.bounds.y1 = sy1;
|
|
|
|
|
srcInfo.bounds.x2 = sx2;
|
|
|
|
|
srcInfo.bounds.y2 = sy2;
|
|
|
|
|
|
|
|
|
|
SurfaceDataRasInfo srcInfo = { .bounds = { sx1, sy1, sx2, sy2 } };
|
|
|
|
|
// NOTE: This function will modify the contents of the bounds field to represent the maximum available raster data.
|
|
|
|
|
if (srcOps->Lock(env, srcOps, &srcInfo, SD_LOCK_READ) != SD_SUCCESS) {
|
|
|
|
|
J2dRlsTraceLn(J2D_TRACE_WARNING, "VKBlitLoops_Blit: could not acquire lock");
|
|
|
|
|
if (src->Lock(env, src, &srcInfo, SD_LOCK_READ) != SD_SUCCESS) {
|
|
|
|
|
J2dRlsTraceLn(J2D_TRACE_WARNING, "VKRenderer_Blit: could not acquire lock");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (srcInfo.bounds.x2 > srcInfo.bounds.x1 && srcInfo.bounds.y2 > srcInfo.bounds.y1) {
|
|
|
|
|
jdouble dstX1 = dx1;
|
|
|
|
|
jdouble dstY1 = dy1;
|
|
|
|
|
jdouble dstX2 = dx2;
|
|
|
|
|
jdouble dstY2 = dy2;
|
|
|
|
|
|
|
|
|
|
srcOps->GetRasInfo(env, srcOps, &srcInfo);
|
|
|
|
|
src->GetRasInfo(env, src, &srcInfo);
|
|
|
|
|
if (srcInfo.rasBase) {
|
|
|
|
|
if (srcInfo.bounds.x1 != sx1) {
|
|
|
|
|
const int dx = srcInfo.bounds.x1 - sx1;
|
|
|
|
|
dstX1 += dx * (dw / sw);
|
|
|
|
|
}
|
|
|
|
|
if (srcInfo.bounds.y1 != sy1) {
|
|
|
|
|
const int dy = srcInfo.bounds.y1 - sy1;
|
|
|
|
|
dstY1 += dy * (dh / sh);
|
|
|
|
|
}
|
|
|
|
|
if (srcInfo.bounds.x2 != sx2) {
|
|
|
|
|
const int dx = srcInfo.bounds.x2 - sx2;
|
|
|
|
|
dstX2 += dx * (dw / sw);
|
|
|
|
|
}
|
|
|
|
|
if (srcInfo.bounds.y2 != sy2) {
|
|
|
|
|
const int dy = srcInfo.bounds.y2 - sy2;
|
|
|
|
|
dstY2 += dy * (dh / sh);
|
|
|
|
|
if (srcInfo.bounds.x1 != sx1) dx1 += (srcInfo.bounds.x1 - sx1) * (dx2 - dx1) / (sx2 - sx1);
|
|
|
|
|
if (srcInfo.bounds.y1 != sy1) dy1 += (srcInfo.bounds.y1 - sy1) * (dy2 - dy1) / (sy2 - sy1);
|
|
|
|
|
if (srcInfo.bounds.x2 != sx2) dx2 += (srcInfo.bounds.x2 - sx2) * (dx2 - dx1) / (sx2 - sx1);
|
|
|
|
|
if (srcInfo.bounds.y2 != sy2) dy2 += (srcInfo.bounds.y2 - sy2) * (dy2 - dy1) / (sy2 - sy1);
|
|
|
|
|
|
|
|
|
|
jint sw = (sx2 = srcInfo.bounds.x2) - (sx1 = srcInfo.bounds.x1);
|
|
|
|
|
jint sh = (sy2 = srcInfo.bounds.y2) - (sy1 = srcInfo.bounds.y1);
|
|
|
|
|
|
|
|
|
|
// Need to validate render pass early, as image may not yet be configured.
|
|
|
|
|
AlphaType alphaType = getSrcAlphaType(srctype);
|
|
|
|
|
if (!VKRenderer_Validate(SHADER_BLIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) return;
|
|
|
|
|
|
|
|
|
|
VKDevice* device = context->surface->device;
|
|
|
|
|
BlitSrcType type = decodeSrcType(device, srctype);
|
|
|
|
|
VKTexturePoolHandle* imageHandle = VKTexturePool_GetTexture(device->texturePool, sw, sh, type.format);
|
|
|
|
|
VKImage* image = VKTexturePoolHandle_GetTexture(imageHandle);
|
|
|
|
|
|
|
|
|
|
VkDeviceSize dataSize = sh * sw * srcInfo.pixelStride;
|
|
|
|
|
VKBuffer buffer;
|
|
|
|
|
VKMemory page = VKBuffer_CreateBuffers(device, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
|
|
|
|
VKBlitLoops_FindStageBufferMemoryType,
|
|
|
|
|
dataSize, 0, &(uint32_t){1}, &buffer);
|
|
|
|
|
|
|
|
|
|
char* raster = (char*) srcInfo.rasBase + sy1 * srcInfo.scanStride + sx1 * srcInfo.pixelStride;
|
|
|
|
|
for (size_t row = 0; row < (size_t) sh; row++) {
|
|
|
|
|
memcpy((char*) buffer.data + row * sw * srcInfo.pixelStride, raster, sw * srcInfo.pixelStride);
|
|
|
|
|
raster += (uint32_t) srcInfo.scanStride;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKBlitSwToTextureViaPooledTexture(context, dstOps, &srcInfo, srctype, hint,
|
|
|
|
|
(int)dstX1, (int)dstY1,
|
|
|
|
|
(int)dstX2, (int)dstY2);
|
|
|
|
|
{
|
|
|
|
|
VkBufferMemoryBarrier bufferBarrier;
|
|
|
|
|
VKBarrierBatch bufferBatch = {};
|
|
|
|
|
VKBuffer_AddBarrier(&bufferBarrier, &bufferBatch, &buffer,
|
|
|
|
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_READ_BIT);
|
|
|
|
|
VkImageMemoryBarrier imageBarrier;
|
|
|
|
|
VKBarrierBatch imageBatch = {};
|
|
|
|
|
VKImage_AddBarrier(&imageBarrier, &imageBatch, image,
|
|
|
|
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
|
|
|
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
|
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
|
|
|
|
VKRenderer_RecordBarriers(device->renderer, &bufferBarrier, &bufferBatch, &imageBarrier, &imageBatch);
|
|
|
|
|
}
|
|
|
|
|
VkBufferImageCopy region = (VkBufferImageCopy) {
|
|
|
|
|
.bufferOffset = 0,
|
|
|
|
|
.bufferRowLength = 0,
|
|
|
|
|
.bufferImageHeight = 0,
|
|
|
|
|
.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
|
.imageSubresource.mipLevel = 0,
|
|
|
|
|
.imageSubresource.baseArrayLayer = 0,
|
|
|
|
|
.imageSubresource.layerCount = 1,
|
|
|
|
|
.imageOffset = {0, 0, 0},
|
|
|
|
|
.imageExtent = {
|
|
|
|
|
.width = sw,
|
|
|
|
|
.height = sh,
|
|
|
|
|
.depth = 1
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
device->vkCmdCopyBufferToImage(VKRenderer_Record(device->renderer), buffer.handle, image->handle,
|
|
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
|
|
|
|
{
|
|
|
|
|
VkImageMemoryBarrier barrier;
|
|
|
|
|
VKBarrierBatch barrierBatch = {};
|
|
|
|
|
VKImage_AddBarrier(&barrier, &barrierBatch, image,
|
|
|
|
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
|
|
|
|
VK_ACCESS_SHADER_READ_BIT,
|
|
|
|
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
|
|
|
|
VKRenderer_RecordBarriers(device->renderer, NULL, NULL, &barrier, &barrierBatch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKRenderer_DrawImage(image, type.format, type.swizzle, hint, SAMPLER_WRAP_BORDER,
|
|
|
|
|
0, 0, (float)sw, (float)sh, (float)dx1, (float)dy1, (float)dx2, (float)dy2);
|
|
|
|
|
|
|
|
|
|
VKRenderer_FlushMemoryOnReset(context->surface->renderPass, buffer.range);
|
|
|
|
|
VKRenderer_ExecOnCleanup(context->surface->renderPass, VKBlitLoops_DisposeTexture, imageHandle);
|
|
|
|
|
VKRenderer_ExecOnCleanup(context->surface->renderPass, VKBlitLoops_DisposeBuffer, buffer.handle);
|
|
|
|
|
VKRenderer_ExecOnCleanup(context->surface->renderPass, VKBlitLoops_DisposeMemory, page);
|
|
|
|
|
} else {
|
|
|
|
|
J2dRlsTraceLn(J2D_TRACE_ERROR, "VKRenderer_Blit: could not get raster info");
|
|
|
|
|
}
|
|
|
|
|
SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
|
|
|
|
|
SurfaceData_InvokeRelease(env, src, &srcInfo);
|
|
|
|
|
}
|
|
|
|
|
SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void VKBlitLoops_FindStageBufferMemoryType(VKMemoryRequirements* requirements) {
|
|
|
|
|
VKAllocator_FindMemoryType(requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
|
|
|
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
|
|
|
|
VKAllocator_FindMemoryType(requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_ALL_MEMORY_PROPERTIES);
|
|
|
|
|
SurfaceData_InvokeUnlock(env, src, &srcInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|