diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index a54297475b..514f91b861 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -14,9 +14,9 @@ namespace struct texel_rgba { template - static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block) + static void copy_mipmap_level(void *dst, void *src, u16 row_count, u16 width_in_block, u16 depth, size_t dst_pitch_in_block, size_t src_pitch_in_block) { - for (unsigned row = 0; row < row_count; row++) + for (unsigned row = 0; row < row_count * depth; row++) memcpy((char*)dst + row * dst_pitch_in_block * block_size, (char*)src + row * src_pitch_in_block * block_size, width_in_block * block_size); } }; @@ -28,13 +28,13 @@ struct texel_rgba struct texel_16b_swizzled { template - static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block) + static void copy_mipmap_level(void *dst, void *src, u16 row_count, u16 width_in_block, u16 depth, size_t dst_pitch_in_block, size_t src_pitch_in_block) { u16 *castedSrc = static_cast(src), *castedDst = static_cast(dst); std::unique_ptr temp_swizzled(new u16[row_count * width_in_block]); rsx::convert_linear_swizzle(castedSrc, temp_swizzled.get(), src_pitch_in_block, row_count, true); - for (unsigned row = 0; row < row_count; row++) + for (unsigned row = 0; row < row_count * depth; row++) for (int j = 0; j < width_in_block; j++) { u16 tmp = temp_swizzled[row * src_pitch_in_block + j]; @@ -49,14 +49,14 @@ struct texel_16b_swizzled struct texel_rgba_swizzled { template - static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block) + static void copy_mipmap_level(void *dst, void *src, u16 row_count, u16 width_in_block, u16 depth, size_t dst_pitch_in_block, size_t src_pitch_in_block) { u32 *castedSrc, *castedDst; castedSrc = (u32*)src; castedDst = (u32*)dst ; std::unique_ptr temp_swizzled(new u32[src_pitch_in_block * row_count]); rsx::convert_linear_swizzle(castedSrc, temp_swizzled.get(), src_pitch_in_block, row_count, true); - for (unsigned row = 0; row < row_count; row++) + for (unsigned row = 0; row < row_count * depth; row++) memcpy((char*)dst + row * dst_pitch_in_block * block_size, (char*)temp_swizzled.get() + row * src_pitch_in_block * block_size, width_in_block * block_size); } }; @@ -67,9 +67,9 @@ struct texel_rgba_swizzled */ struct texel_bc_format { template - static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block) + static void copy_mipmap_level(void *dst, void *src, u16 row_count, u16 width_in_block, u16 depth, size_t dst_pitch_in_block, size_t src_pitch_in_block) { - for (unsigned row = 0; row < row_count; row++) + for (unsigned row = 0; row < row_count * depth; row++) memcpy((char*)dst + row * dst_pitch_in_block * block_size, (char*)src + row * src_pitch_in_block * block_size, width_in_block * block_size); } }; @@ -79,11 +79,11 @@ struct texel_bc_format { */ struct texel_16b_format { template - static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block) + static void copy_mipmap_level(void *dst, void *src, u16 row_count, u16 width_in_block, u16 depth, size_t dst_pitch_in_block, size_t src_pitch_in_block) { unsigned short *castedDst = (unsigned short *)dst, *castedSrc = (unsigned short *)src; - for (unsigned row = 0; row < row_count; row++) + for (unsigned row = 0; row < row_count * depth; row++) for (int j = 0; j < width_in_block; j++) { u16 tmp = castedSrc[row * src_pitch_in_block + j]; @@ -97,10 +97,10 @@ struct texel_16b_format { */ struct texel_16bX4_format { template - static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block) + static void copy_mipmap_level(void *dst, void *src, u16 row_count, u16 width_in_block, u16 depth, size_t dst_pitch_in_block, size_t src_pitch_in_block) { unsigned short *casted_dst = (unsigned short *)dst, *casted_src = (unsigned short *)src; - for (unsigned row = 0; row < row_count; row++) + for (unsigned row = 0; row < row_count * depth; row++) for (int j = 0; j < width_in_block * 4; j++) { u16 tmp = casted_src[row * src_pitch_in_block * 4 + j]; @@ -124,13 +124,13 @@ struct texel_16bX4_format { * mipmap level (to allow same code for packed/non packed texels) */ template -std::vector copy_texture_data(void *dst, const void *src, size_t width_in_texel, size_t height_in_texel, size_t depth, size_t mipmap_count) +std::vector copy_texture_data(void *dst, const void *src, u16 width_in_texel, u16 height_in_texel, u16 depth, u8 layer_count, u16 mipmap_count) { std::vector Result; size_t offsetInDst = 0, offsetInSrc = 0; size_t texture_height_in_block = (height_in_texel + block_edge_in_texel - 1) / block_edge_in_texel; size_t texture_width_in_block = (width_in_texel + block_edge_in_texel - 1) / block_edge_in_texel; - for (unsigned depth_level = 0; depth_level < depth; depth_level++) + for (unsigned layer = 0; layer < layer_count; layer++) { size_t miplevel_height_in_block = texture_height_in_block, miplevel_width_in_block = texture_width_in_block; for (unsigned mip_level = 0; mip_level < mipmap_count; mip_level++) @@ -141,18 +141,19 @@ std::vector copy_texture_data(void *dst, const void *src, size_ currentMipmapLevelInfo.offset = offsetInDst; currentMipmapLevelInfo.height = miplevel_height_in_block * block_edge_in_texel; currentMipmapLevelInfo.width = miplevel_width_in_block * block_edge_in_texel; + currentMipmapLevelInfo.depth = depth; currentMipmapLevelInfo.rowPitch = dst_pitch * block_size_in_bytes; Result.push_back(currentMipmapLevelInfo); if (!padded_row) { - T::template copy_mipmap_level((char*)dst + offsetInDst, (char*)src + offsetInSrc, miplevel_height_in_block, miplevel_width_in_block, dst_pitch, miplevel_width_in_block); - offsetInSrc += miplevel_height_in_block * miplevel_width_in_block * block_size_in_bytes; + T::template copy_mipmap_level((char*)dst + offsetInDst, (char*)src + offsetInSrc, miplevel_height_in_block, miplevel_width_in_block, depth, dst_pitch, miplevel_width_in_block); + offsetInSrc += miplevel_height_in_block * miplevel_width_in_block * block_size_in_bytes * depth; } else { - T::template copy_mipmap_level((char*)dst + offsetInDst, (char*)src + offsetInSrc, miplevel_height_in_block, miplevel_width_in_block, dst_pitch, texture_width_in_block); - offsetInSrc += miplevel_height_in_block * texture_width_in_block * block_size_in_bytes; + T::template copy_mipmap_level((char*)dst + offsetInDst, (char*)src + offsetInSrc, miplevel_height_in_block, miplevel_width_in_block, depth, dst_pitch, texture_width_in_block); + offsetInSrc += miplevel_height_in_block * texture_width_in_block * block_size_in_bytes * depth; } offsetInDst += align(miplevel_height_in_block * dst_pitch * block_size_in_bytes, 512); miplevel_height_in_block = MAX2(miplevel_height_in_block / 2, 1); @@ -265,10 +266,22 @@ size_t get_placed_texture_storage_size(const rsx::texture &texture, size_t rowPi std::vector upload_placed_texture(const rsx::texture &texture, size_t rowPitchAlignement, void* textureData) { - size_t w = texture.width(), h = texture.height(); - size_t depth = texture.depth(); - if (depth == 0) depth = 1; - if (texture.cubemap()) depth *= 6; + u16 w = texture.width(), h = texture.height(); + u16 depth; + u8 layer; + + if (texture.dimension() == 2) + { + depth = 1; + layer = texture.cubemap() ? 6 : 1; + } + else if (texture.dimension() == 3) + { + depth = texture.depth(); + layer = 1; + } + else + throw EXCEPTION("Unsupported texture dimension %d", texture.dimension()); int format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); @@ -281,37 +294,37 @@ std::vector upload_placed_texture(const rsx::texture &texture, { case CELL_GCM_TEXTURE_A8R8G8B8: if (is_swizzled) - return copy_texture_data(textureData, pixels, w, h, depth, texture.mipmap()); + return copy_texture_data(textureData, pixels, w, h, depth, layer, texture.mipmap()); else - return copy_texture_data(textureData, pixels, w, h, depth, texture.mipmap()); + return copy_texture_data(textureData, pixels, w, h, depth, layer, texture.mipmap()); case CELL_GCM_TEXTURE_A1R5G5B5: case CELL_GCM_TEXTURE_A4R4G4B4: case CELL_GCM_TEXTURE_R5G6B5: if (is_swizzled) - return copy_texture_data(textureData, pixels, w, h, depth, texture.mipmap()); + return copy_texture_data(textureData, pixels, w, h, depth, layer, texture.mipmap()); else - return copy_texture_data(textureData, pixels, w, h, depth, texture.mipmap()); + return copy_texture_data(textureData, pixels, w, h, depth, layer, texture.mipmap()); case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: - return copy_texture_data(textureData, pixels, w, h, depth, texture.mipmap()); + return copy_texture_data(textureData, pixels, w, h, depth, layer, texture.mipmap()); case CELL_GCM_TEXTURE_COMPRESSED_DXT1: if (is_swizzled) - return copy_texture_data(textureData, pixels, w, h, depth, texture.mipmap()); + return copy_texture_data(textureData, pixels, w, h, depth, layer, texture.mipmap()); else - return copy_texture_data(textureData, pixels, w, h, depth, texture.mipmap()); + return copy_texture_data(textureData, pixels, w, h, depth, layer, texture.mipmap()); case CELL_GCM_TEXTURE_COMPRESSED_DXT23: if (is_swizzled) - return copy_texture_data(textureData, pixels, w, h, depth, texture.mipmap()); + return copy_texture_data(textureData, pixels, w, h, depth, layer, texture.mipmap()); else - return copy_texture_data(textureData, pixels, w, h, depth, texture.mipmap()); + return copy_texture_data(textureData, pixels, w, h, depth, layer, texture.mipmap()); case CELL_GCM_TEXTURE_COMPRESSED_DXT45: if (is_swizzled) - return copy_texture_data(textureData, pixels, w, h, depth, texture.mipmap()); + return copy_texture_data(textureData, pixels, w, h, depth, layer, texture.mipmap()); else - return copy_texture_data(textureData, pixels, w, h, depth, texture.mipmap()); + return copy_texture_data(textureData, pixels, w, h, depth, layer, texture.mipmap()); case CELL_GCM_TEXTURE_B8: - return copy_texture_data(textureData, pixels, w, h, depth, texture.mipmap()); + return copy_texture_data(textureData, pixels, w, h, depth, layer, texture.mipmap()); default: - return copy_texture_data(textureData, pixels, w, h, depth, texture.mipmap()); + return copy_texture_data(textureData, pixels, w, h, depth, layer, texture.mipmap()); } } diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.h b/rpcs3/Emu/RSX/Common/TextureUtils.h index 28e1fad5b8..4ba3a86549 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.h +++ b/rpcs3/Emu/RSX/Common/TextureUtils.h @@ -5,9 +5,10 @@ struct MipmapLevelInfo { size_t offset; - size_t width; - size_t height; - size_t rowPitch; + u16 width; + u16 height; + u16 depth; + u16 rowPitch; }; /** diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp index 59a9674950..1d183d4042 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp @@ -40,6 +40,27 @@ D3D12_SAMPLER_DESC get_sampler_desc(const rsx::texture &texture) return samplerDesc; } +namespace +{ + CD3DX12_RESOURCE_DESC get_texture_description(const rsx::texture &texture) + { + const u8 format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); + DXGI_FORMAT dxgi_format = get_texture_format(format); + + if (texture.dimension() == 2) // 2D texture or cubemap + { +// if (texture.depth() < 2); + size_t depth = (texture.cubemap()) ? 6 : 1; + return CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, texture.width(), texture.height(), (UINT)depth, texture.mipmap()); + } + else if (texture.dimension() == 3) // 3d texture + { + return CD3DX12_RESOURCE_DESC::Tex3D(dxgi_format, texture.width(), texture.height(), texture.depth(), texture.mipmap()); + } + throw EXCEPTION("Unknow texture dimension"); + } +} + /** * Create a texture residing in default heap and generate uploads commands in commandList, @@ -51,14 +72,6 @@ ComPtr upload_single_texture( ID3D12GraphicsCommandList *command_list, data_heap &texture_buffer_heap) { - size_t w = texture.width(), h = texture.height(); - size_t depth = texture.depth(); - if (depth == 0) depth = 1; - if (texture.cubemap()) depth *= 6; - - const u8 format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); - DXGI_FORMAT dxgi_format = get_texture_format(format); - size_t buffer_size = get_placed_texture_storage_size(texture, 256); size_t heap_offset = texture_buffer_heap.alloc(buffer_size); @@ -70,17 +83,19 @@ ComPtr upload_single_texture( CHECK_HRESULT(device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)w, (UINT)h, (UINT)depth, texture.mipmap()), + &get_texture_description(texture), D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(result.GetAddressOf()) )); + const u8 format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); + DXGI_FORMAT dxgi_format = get_texture_format(format); size_t mip_level = 0; for (const MipmapLevelInfo mli : mipInfos) { command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(result.Get(), (UINT)mip_level), 0, 0, 0, - &CD3DX12_TEXTURE_COPY_LOCATION(texture_buffer_heap.get_heap(), { heap_offset + mli.offset, { dxgi_format, (UINT)mli.width, (UINT)mli.height, 1, (UINT)mli.rowPitch } }), nullptr); + &CD3DX12_TEXTURE_COPY_LOCATION(texture_buffer_heap.get_heap(), { heap_offset + mli.offset, { dxgi_format, (UINT)mli.width, (UINT)mli.height, (UINT)mli.depth, (UINT)mli.rowPitch } }), nullptr); mip_level++; } @@ -114,7 +129,7 @@ void update_existing_texture( for (const MipmapLevelInfo mli : mipInfos) { command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(existing_texture, (UINT)miplevel), 0, 0, 0, - &CD3DX12_TEXTURE_COPY_LOCATION(texture_buffer_heap.get_heap(), { heap_offset + mli.offset,{ dxgi_format, (UINT)mli.width, (UINT)mli.height, 1, (UINT)mli.rowPitch } }), nullptr); + &CD3DX12_TEXTURE_COPY_LOCATION(texture_buffer_heap.get_heap(), { heap_offset + mli.offset,{ dxgi_format, (UINT)mli.width, (UINT)mli.height, (UINT)mli.depth, (UINT)mli.rowPitch } }), nullptr); miplevel++; } @@ -204,11 +219,16 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_ shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; shared_resource_view_desc.TextureCube.MipLevels = textures[i].mipmap(); } - else + else if (textures[i].dimension() == 2) { shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; shared_resource_view_desc.Texture2D.MipLevels = textures[i].mipmap(); } + else if (textures[i].dimension() == 3) + { + shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; + shared_resource_view_desc.Texture2D.MipLevels = textures[i].mipmap(); + } shared_resource_view_desc.Format = get_texture_format(format); switch (format)