wined3d: Implement Vulkan texture uploads.
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
07981fa64f
commit
3685c2199b
|
@ -550,6 +550,32 @@ void wined3d_context_vk_wait_command_buffer(struct wined3d_context_vk *context_v
|
|||
ERR("Failed to find fence for command buffer with id 0x%s.\n", wine_dbgstr_longlong(id));
|
||||
}
|
||||
|
||||
void wined3d_context_vk_image_barrier(struct wined3d_context_vk *context_vk,
|
||||
VkCommandBuffer vk_command_buffer, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
|
||||
VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask, VkImageLayout old_layout,
|
||||
VkImageLayout new_layout, VkImage image, VkImageAspectFlags aspect_mask)
|
||||
{
|
||||
const struct wined3d_vk_info *vk_info = context_vk->vk_info;
|
||||
VkImageMemoryBarrier barrier;
|
||||
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barrier.pNext = NULL;
|
||||
barrier.srcAccessMask = src_access_mask;
|
||||
barrier.dstAccessMask = dst_access_mask;
|
||||
barrier.oldLayout = old_layout;
|
||||
barrier.newLayout = new_layout;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.image = image;
|
||||
barrier.subresourceRange.aspectMask = aspect_mask;
|
||||
barrier.subresourceRange.baseMipLevel = 0;
|
||||
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
barrier.subresourceRange.baseArrayLayer = 0;
|
||||
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
|
||||
VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, src_stage_mask, dst_stage_mask, 0, 0, NULL, 0, NULL, 1, &barrier));
|
||||
}
|
||||
|
||||
HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wined3d_swapchain *swapchain)
|
||||
{
|
||||
VkCommandPoolCreateInfo command_pool_info;
|
||||
|
|
|
@ -4218,7 +4218,143 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context,
|
|||
struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, unsigned int dst_location,
|
||||
unsigned int dst_x, unsigned int dst_y, unsigned int dst_z)
|
||||
{
|
||||
FIXME("Not implemented.\n");
|
||||
struct wined3d_texture_vk *dst_texture_vk = wined3d_texture_vk(dst_texture);
|
||||
struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
|
||||
unsigned int dst_level, dst_row_pitch, dst_slice_pitch;
|
||||
struct wined3d_texture_sub_resource *sub_resource;
|
||||
struct wined3d_bo_address staging_bo_addr;
|
||||
const struct wined3d_vk_info *vk_info;
|
||||
VkCommandBuffer vk_command_buffer;
|
||||
struct wined3d_bo_vk staging_bo;
|
||||
VkImageAspectFlags aspect_mask;
|
||||
size_t src_offset, dst_offset;
|
||||
struct wined3d_range range;
|
||||
VkBufferImageCopy region;
|
||||
void *map_ptr;
|
||||
|
||||
TRACE("context %p, src_bo_addr %s, src_format %s, src_box %s, src_row_pitch %u, src_slice_pitch %u, "
|
||||
"dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_x %u, dst_y %u, dst_z %u.\n",
|
||||
context, debug_const_bo_address(src_bo_addr), debug_d3dformat(src_format->id), debug_box(src_box),
|
||||
src_row_pitch, src_slice_pitch, dst_texture, dst_sub_resource_idx,
|
||||
wined3d_debug_location(dst_location), dst_x, dst_y, dst_z);
|
||||
|
||||
if (src_bo_addr->buffer_object)
|
||||
{
|
||||
FIXME("Unhandled buffer object %#lx.\n", src_bo_addr->buffer_object);
|
||||
return;
|
||||
}
|
||||
|
||||
if (src_format->id != dst_texture->resource.format->id)
|
||||
{
|
||||
FIXME("Unhandled format conversion (%s -> %s).\n",
|
||||
debug_d3dformat(src_format->id),
|
||||
debug_d3dformat(dst_texture->resource.format->id));
|
||||
return;
|
||||
}
|
||||
|
||||
dst_level = dst_sub_resource_idx % dst_texture->level_count;
|
||||
wined3d_texture_get_pitch(dst_texture, dst_level, &dst_row_pitch, &dst_slice_pitch);
|
||||
if (dst_texture->resource.type == WINED3D_RTYPE_TEXTURE_1D)
|
||||
src_row_pitch = dst_row_pitch = 0;
|
||||
if (dst_texture->resource.type != WINED3D_RTYPE_TEXTURE_3D)
|
||||
src_slice_pitch = dst_slice_pitch = 0;
|
||||
|
||||
if (dst_location != WINED3D_LOCATION_TEXTURE_RGB)
|
||||
{
|
||||
FIXME("Unhandled location %s.\n", wined3d_debug_location(dst_location));
|
||||
return;
|
||||
}
|
||||
|
||||
if (wined3d_resource_get_sample_count(&dst_texture_vk->t.resource) > 1)
|
||||
{
|
||||
FIXME("Not supported for multisample textures.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
aspect_mask = vk_aspect_mask_from_format(dst_texture->resource.format);
|
||||
if (wined3d_popcount(aspect_mask) > 1)
|
||||
{
|
||||
FIXME("Unhandled multi-aspect format %s.\n", debug_d3dformat(dst_texture->resource.format->id));
|
||||
return;
|
||||
}
|
||||
|
||||
sub_resource = &dst_texture_vk->t.sub_resources[dst_sub_resource_idx];
|
||||
vk_info = context_vk->vk_info;
|
||||
|
||||
src_offset = src_box->front * src_slice_pitch
|
||||
+ (src_box->top / src_format->block_height) * src_row_pitch
|
||||
+ (src_box->left / src_format->block_width) * src_format->block_byte_count;
|
||||
dst_offset = dst_z * src_slice_pitch
|
||||
+ (dst_y / src_format->block_height) * src_row_pitch
|
||||
+ (dst_x / src_format->block_width) * src_format->block_byte_count;
|
||||
|
||||
if (!wined3d_context_vk_create_bo(context_vk, sub_resource->size,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_bo))
|
||||
{
|
||||
ERR("Failed to create staging bo.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
staging_bo_addr.buffer_object = (uintptr_t)&staging_bo;
|
||||
staging_bo_addr.addr = NULL;
|
||||
if (!(map_ptr = wined3d_context_map_bo_address(context, &staging_bo_addr,
|
||||
sub_resource->size, 0, WINED3D_MAP_DISCARD | WINED3D_MAP_WRITE)))
|
||||
{
|
||||
ERR("Failed to map staging bo.\n");
|
||||
wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
|
||||
return;
|
||||
}
|
||||
|
||||
wined3d_format_copy_data(src_format, src_bo_addr->addr + src_offset, src_row_pitch, src_slice_pitch,
|
||||
(uint8_t *)map_ptr + dst_offset, dst_row_pitch, dst_slice_pitch, src_box->right - src_box->left,
|
||||
src_box->bottom - src_box->top, src_box->back - src_box->front);
|
||||
|
||||
range.offset = 0;
|
||||
range.size = sub_resource->size;
|
||||
wined3d_context_unmap_bo_address(context, &staging_bo_addr, 0, 1, &range);
|
||||
|
||||
if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
|
||||
{
|
||||
ERR("Failed to get command buffer.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
vk_access_mask_from_bind_flags(dst_texture_vk->t.resource.bind_flags),
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
dst_texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
dst_texture_vk->vk_image, aspect_mask);
|
||||
|
||||
region.bufferOffset = dst_offset;
|
||||
region.bufferRowLength = (dst_row_pitch / src_format->block_byte_count) * src_format->block_width;
|
||||
if (dst_row_pitch)
|
||||
region.bufferImageHeight = (dst_slice_pitch / dst_row_pitch) * src_format->block_height;
|
||||
else
|
||||
region.bufferImageHeight = 1;
|
||||
region.imageSubresource.aspectMask = aspect_mask;
|
||||
region.imageSubresource.mipLevel = dst_level;
|
||||
region.imageSubresource.baseArrayLayer = dst_sub_resource_idx / dst_texture_vk->t.level_count;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageOffset.x = dst_x;
|
||||
region.imageOffset.y = dst_y;
|
||||
region.imageOffset.z = dst_z;
|
||||
region.imageExtent.width = src_box->right - src_box->left;
|
||||
region.imageExtent.height = src_box->bottom - src_box->top;
|
||||
region.imageExtent.depth = src_box->back - src_box->front;
|
||||
|
||||
VK_CALL(vkCmdCopyBufferToImage(vk_command_buffer, staging_bo.vk_buffer,
|
||||
dst_texture_vk->vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion));
|
||||
|
||||
wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
vk_access_mask_from_bind_flags(dst_texture_vk->t.resource.bind_flags),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_texture_vk->layout,
|
||||
dst_texture_vk->vk_image, aspect_mask);
|
||||
dst_texture_vk->command_buffer_id = context_vk->current_command_buffer.id;
|
||||
staging_bo.command_buffer_id = context_vk->current_command_buffer.id;
|
||||
wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
|
||||
}
|
||||
|
||||
static void wined3d_texture_vk_download_data(struct wined3d_context *context,
|
||||
|
@ -4230,6 +4366,32 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context,
|
|||
FIXME("Not implemented.\n");
|
||||
}
|
||||
|
||||
static BOOL wined3d_texture_vk_load_texture(struct wined3d_texture_vk *texture_vk,
|
||||
unsigned int sub_resource_idx, struct wined3d_context *context)
|
||||
{
|
||||
struct wined3d_texture_sub_resource *sub_resource;
|
||||
unsigned int level, row_pitch, slice_pitch;
|
||||
struct wined3d_bo_address data;
|
||||
struct wined3d_box src_box;
|
||||
|
||||
sub_resource = &texture_vk->t.sub_resources[sub_resource_idx];
|
||||
if (!(sub_resource->locations & WINED3D_LOCATION_SYSMEM))
|
||||
{
|
||||
ERR("Unimplemented load from %s.\n", wined3d_debug_location(sub_resource->locations));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
level = sub_resource_idx % texture_vk->t.level_count;
|
||||
wined3d_texture_get_memory(&texture_vk->t, sub_resource_idx, &data, WINED3D_LOCATION_SYSMEM);
|
||||
wined3d_texture_get_level_box(&texture_vk->t, level, &src_box);
|
||||
wined3d_texture_get_pitch(&texture_vk->t, level, &row_pitch, &slice_pitch);
|
||||
wined3d_texture_vk_upload_data(context, wined3d_const_bo_address(&data), texture_vk->t.resource.format,
|
||||
&src_box, row_pitch, slice_pitch, &texture_vk->t, sub_resource_idx,
|
||||
WINED3D_LOCATION_TEXTURE_RGB, 0, 0, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk *texture_vk,
|
||||
struct wined3d_context_vk *context_vk)
|
||||
{
|
||||
|
@ -4239,6 +4401,7 @@ static BOOL wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk *textur
|
|||
struct wined3d_adapter_vk *adapter_vk;
|
||||
struct wined3d_device_vk *device_vk;
|
||||
struct wined3d_resource *resource;
|
||||
VkCommandBuffer vk_command_buffer;
|
||||
VkImageCreateInfo create_info;
|
||||
unsigned int memory_type_idx;
|
||||
VkResult vr;
|
||||
|
@ -4246,6 +4409,12 @@ static BOOL wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk *textur
|
|||
if (texture_vk->t.flags & WINED3D_TEXTURE_RGB_ALLOCATED)
|
||||
return TRUE;
|
||||
|
||||
if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
|
||||
{
|
||||
ERR("Failed to get command buffer.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
resource = &texture_vk->t.resource;
|
||||
device_vk = wined3d_device_vk(resource->device);
|
||||
adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
|
||||
|
@ -4299,6 +4468,28 @@ static BOOL wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk *textur
|
|||
if (resource->bind_flags & WINED3D_BIND_UNORDERED_ACCESS)
|
||||
create_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
|
||||
texture_vk->layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
if (wined3d_popcount(resource->bind_flags == 1))
|
||||
{
|
||||
switch (resource->bind_flags)
|
||||
{
|
||||
case WINED3D_BIND_RENDER_TARGET:
|
||||
texture_vk->layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
break;
|
||||
|
||||
case WINED3D_BIND_DEPTH_STENCIL:
|
||||
texture_vk->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
break;
|
||||
|
||||
case WINED3D_BIND_SHADER_RESOURCE:
|
||||
texture_vk->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
create_info.queueFamilyIndexCount = 0;
|
||||
create_info.pQueueFamilyIndices = NULL;
|
||||
|
@ -4345,6 +4536,13 @@ static BOOL wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk *textur
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
texture_vk->command_buffer_id = context_vk->current_command_buffer.id;
|
||||
wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
0, 0,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, texture_vk->layout,
|
||||
texture_vk->vk_image, vk_aspect_mask_from_format(&format_vk->f));
|
||||
|
||||
texture_vk->t.flags |= WINED3D_TEXTURE_RGB_ALLOCATED;
|
||||
|
||||
TRACE("Created image 0x%s, memory 0x%s for texture %p.\n",
|
||||
|
@ -4378,9 +4576,18 @@ static BOOL wined3d_texture_vk_prepare_location(struct wined3d_texture *texture,
|
|||
static BOOL wined3d_texture_vk_load_location(struct wined3d_texture *texture,
|
||||
unsigned int sub_resource_idx, struct wined3d_context *context, DWORD location)
|
||||
{
|
||||
FIXME("Not implemented.\n");
|
||||
if (!wined3d_texture_vk_prepare_location(texture, sub_resource_idx, context, location))
|
||||
return FALSE;
|
||||
|
||||
return FALSE;
|
||||
switch (location)
|
||||
{
|
||||
case WINED3D_LOCATION_TEXTURE_RGB:
|
||||
return wined3d_texture_vk_load_texture(wined3d_texture_vk(texture), sub_resource_idx, context);
|
||||
|
||||
default:
|
||||
FIXME("Unimplemented location %s.\n", wined3d_debug_location(location));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void wined3d_texture_vk_unload_location(struct wined3d_texture *texture,
|
||||
|
|
|
@ -5977,6 +5977,36 @@ enum wined3d_format_id pixelformat_for_depth(DWORD depth)
|
|||
}
|
||||
}
|
||||
|
||||
void wined3d_format_copy_data(const struct wined3d_format *format, const uint8_t *src,
|
||||
unsigned int src_row_pitch, unsigned int src_slice_pitch, uint8_t *dst, unsigned int dst_row_pitch,
|
||||
unsigned int dst_slice_pitch, unsigned int w, unsigned int h, unsigned int d)
|
||||
{
|
||||
unsigned int row_block_count, row_count, row_size, slice, row;
|
||||
unsigned int slice_count = d;
|
||||
const uint8_t *src_row;
|
||||
uint8_t *dst_row;
|
||||
|
||||
row_block_count = (w + format->block_width - 1) / format->block_width;
|
||||
row_count = (h + format->block_height - 1) / format->block_height;
|
||||
row_size = row_block_count * format->block_byte_count;
|
||||
|
||||
if (src_row_pitch == row_size && dst_row_pitch == row_size && src_slice_pitch == dst_slice_pitch)
|
||||
{
|
||||
memcpy(dst, src, slice_count * row_count * row_size);
|
||||
return;
|
||||
}
|
||||
|
||||
for (slice = 0; slice < slice_count; ++slice)
|
||||
{
|
||||
for (row = 0; row < row_count; ++row)
|
||||
{
|
||||
src_row = &src[slice * src_slice_pitch + row * src_row_pitch];
|
||||
dst_row = &dst[slice * dst_slice_pitch + row * dst_row_pitch];
|
||||
memcpy(dst_row, src_row, row_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void multiply_matrix(struct wined3d_matrix *dst, const struct wined3d_matrix *src1, const struct wined3d_matrix *src2)
|
||||
{
|
||||
struct wined3d_matrix tmp;
|
||||
|
|
|
@ -2261,6 +2261,10 @@ void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk,
|
|||
void wined3d_context_vk_destroy_memory(struct wined3d_context_vk *context_vk,
|
||||
VkDeviceMemory vk_memory, uint64_t command_buffer_id) DECLSPEC_HIDDEN;
|
||||
VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN;
|
||||
void wined3d_context_vk_image_barrier(struct wined3d_context_vk *context_vk,
|
||||
VkCommandBuffer vk_command_buffer, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
|
||||
VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask, VkImageLayout old_layout,
|
||||
VkImageLayout new_layout, VkImage image, VkImageAspectFlags aspect_mask) DECLSPEC_HIDDEN;
|
||||
HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk,
|
||||
struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
|
||||
void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context_vk,
|
||||
|
@ -3958,6 +3962,7 @@ struct wined3d_texture_vk
|
|||
VkImage vk_image;
|
||||
struct wined3d_allocator_block *memory;
|
||||
VkDeviceMemory vk_memory;
|
||||
enum VkImageLayout layout;
|
||||
uint64_t command_buffer_id;
|
||||
};
|
||||
|
||||
|
@ -5155,6 +5160,9 @@ UINT wined3d_format_calculate_size(const struct wined3d_format *format,
|
|||
UINT alignment, UINT width, UINT height, UINT depth) DECLSPEC_HIDDEN;
|
||||
DWORD wined3d_format_convert_from_float(const struct wined3d_format *format,
|
||||
const struct wined3d_color *color) DECLSPEC_HIDDEN;
|
||||
void wined3d_format_copy_data(const struct wined3d_format *format, const uint8_t *src,
|
||||
unsigned int src_row_pitch, unsigned int src_slice_pitch, uint8_t *dst, unsigned int dst_row_pitch,
|
||||
unsigned int dst_slice_pitch, unsigned int w, unsigned int h, unsigned int d) DECLSPEC_HIDDEN;
|
||||
void wined3d_format_get_float_color_key(const struct wined3d_format *format,
|
||||
const struct wined3d_color_key *key, struct wined3d_color *float_colors) DECLSPEC_HIDDEN;
|
||||
BOOL wined3d_format_is_depth_view(enum wined3d_format_id resource_format_id,
|
||||
|
@ -5538,6 +5546,20 @@ static inline BOOL wined3d_bitmap_get_range(const DWORD *bitmap, unsigned int bi
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static inline VkImageAspectFlags vk_aspect_mask_from_format(const struct wined3d_format *format)
|
||||
{
|
||||
VkImageAspectFlags mask = 0;
|
||||
|
||||
if (format->depth_size)
|
||||
mask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if (format->stencil_size)
|
||||
mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
if (!mask || format->red_size || format->green_size || format->blue_size || format->alpha_size)
|
||||
mask |= VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */
|
||||
#define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"
|
||||
|
||||
|
|
Loading…
Reference in New Issue