Quellcode durchsuchen

gpu: D3D12 uploads should also factor in block size for height, not just width.

It turns out the reason this function was having so many overread issues was because our row copies were wrong - for compressed images we also need to reduce the row count based on the block size, similar to what we already do for pitch calculation - these copies are byte copies, not pixel copies!
Ethan Lee vor 2 Monaten
Ursprung
Commit
f472f93db8
1 geänderte Dateien mit 14 neuen und 16 gelöschten Zeilen
  1. 14 16
      src/gpu/d3d12/SDL_gpu_d3d12.c

+ 14 - 16
src/gpu/d3d12/SDL_gpu_d3d12.c

@@ -5922,7 +5922,10 @@ static void D3D12_UploadToTexture(
     D3D12_TEXTURE_COPY_LOCATION sourceLocation;
     D3D12_TEXTURE_COPY_LOCATION sourceLocation;
     D3D12_TEXTURE_COPY_LOCATION destinationLocation;
     D3D12_TEXTURE_COPY_LOCATION destinationLocation;
     Uint32 pixelsPerRow = source->pixels_per_row;
     Uint32 pixelsPerRow = source->pixels_per_row;
+    Uint32 blockWidth;
+    Uint32 blockSize;
     Uint32 rowPitch;
     Uint32 rowPitch;
+    Uint32 blockHeight;
     Uint32 alignedRowPitch;
     Uint32 alignedRowPitch;
     Uint32 rowsPerSlice = source->rows_per_layer;
     Uint32 rowsPerSlice = source->rows_per_layer;
     Uint32 bytesPerSlice;
     Uint32 bytesPerSlice;
@@ -5956,15 +5959,18 @@ static void D3D12_UploadToTexture(
         pixelsPerRow = destination->w;
         pixelsPerRow = destination->w;
     }
     }
 
 
-    rowPitch = BytesPerRow(pixelsPerRow, textureContainer->header.info.format);
-
     if (rowsPerSlice == 0) {
     if (rowsPerSlice == 0) {
         rowsPerSlice = destination->h;
         rowsPerSlice = destination->h;
     }
     }
 
 
+    blockWidth = Texture_GetBlockWidth(textureContainer->header.info.format);
+    blockSize = SDL_GPUTextureFormatTexelBlockSize(textureContainer->header.info.format);
+    rowPitch = (pixelsPerRow + (blockWidth - 1)) / blockWidth * blockSize;
+    blockHeight = (rowsPerSlice + (blockWidth - 1)) / blockWidth;
+
     bytesPerSlice = rowsPerSlice * rowPitch;
     bytesPerSlice = rowsPerSlice * rowPitch;
 
 
-    alignedRowPitch = BytesPerRow(destination->w, textureContainer->header.info.format);
+    alignedRowPitch = (destination->w + (blockWidth - 1)) / blockWidth * blockSize;
     alignedRowPitch = D3D12_INTERNAL_Align(alignedRowPitch, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
     alignedRowPitch = D3D12_INTERNAL_Align(alignedRowPitch, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
     needsRealignment = rowsPerSlice != destination->h || rowPitch != alignedRowPitch;
     needsRealignment = rowsPerSlice != destination->h || rowPitch != alignedRowPitch;
     needsPlacementCopy = source->offset % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT != 0;
     needsPlacementCopy = source->offset % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT != 0;
@@ -5983,7 +5989,7 @@ static void D3D12_UploadToTexture(
         temporaryBuffer = D3D12_INTERNAL_CreateBuffer(
         temporaryBuffer = D3D12_INTERNAL_CreateBuffer(
             d3d12CommandBuffer->renderer,
             d3d12CommandBuffer->renderer,
             0,
             0,
-            alignedRowPitch * destination->h * destination->d,
+            alignedRowPitch * blockHeight * destination->d,
             D3D12_BUFFER_TYPE_UPLOAD,
             D3D12_BUFFER_TYPE_UPLOAD,
             NULL);
             NULL);
 
 
@@ -5994,21 +6000,13 @@ static void D3D12_UploadToTexture(
         sourceLocation.pResource = temporaryBuffer->handle;
         sourceLocation.pResource = temporaryBuffer->handle;
 
 
         for (Uint32 sliceIndex = 0; sliceIndex < destination->d; sliceIndex += 1) {
         for (Uint32 sliceIndex = 0; sliceIndex < destination->d; sliceIndex += 1) {
-            // copy row count minus one to avoid overread
-            for (Uint32 rowIndex = 0; rowIndex < destination->h - 1; rowIndex += 1) {
-
+            for (Uint32 rowIndex = 0; rowIndex < blockHeight; rowIndex += 1) {
                 SDL_memcpy(
                 SDL_memcpy(
                     temporaryBuffer->mapPointer + (sliceIndex * alignedBytesPerSlice) + (rowIndex * alignedRowPitch),
                     temporaryBuffer->mapPointer + (sliceIndex * alignedBytesPerSlice) + (rowIndex * alignedRowPitch),
                     transferBufferContainer->activeBuffer->mapPointer + source->offset + (sliceIndex * bytesPerSlice) + (rowIndex * rowPitch),
                     transferBufferContainer->activeBuffer->mapPointer + source->offset + (sliceIndex * bytesPerSlice) + (rowIndex * rowPitch),
-                    alignedRowPitch);
+                    rowPitch);
 
 
             }
             }
-            Uint32 offset = source->offset + (sliceIndex * bytesPerSlice) + ((destination->h - 1) * rowPitch);
-
-            SDL_memcpy(
-                temporaryBuffer->mapPointer + (sliceIndex * alignedBytesPerSlice) + ((destination->h - 1) * alignedRowPitch),
-                transferBufferContainer->activeBuffer->mapPointer + offset,
-                SDL_min(alignedRowPitch, transferBufferContainer->size - offset));
 
 
             sourceLocation.PlacedFootprint.Footprint.Width = destination->w;
             sourceLocation.PlacedFootprint.Footprint.Width = destination->w;
             sourceLocation.PlacedFootprint.Footprint.Height = destination->h;
             sourceLocation.PlacedFootprint.Footprint.Height = destination->h;
@@ -6037,7 +6035,7 @@ static void D3D12_UploadToTexture(
         temporaryBuffer = D3D12_INTERNAL_CreateBuffer(
         temporaryBuffer = D3D12_INTERNAL_CreateBuffer(
             d3d12CommandBuffer->renderer,
             d3d12CommandBuffer->renderer,
             0,
             0,
-            alignedRowPitch * destination->h * destination->d,
+            alignedRowPitch * blockHeight * destination->d,
             D3D12_BUFFER_TYPE_UPLOAD,
             D3D12_BUFFER_TYPE_UPLOAD,
             NULL);
             NULL);
 
 
@@ -6048,7 +6046,7 @@ static void D3D12_UploadToTexture(
         SDL_memcpy(
         SDL_memcpy(
             temporaryBuffer->mapPointer,
             temporaryBuffer->mapPointer,
             transferBufferContainer->activeBuffer->mapPointer + source->offset,
             transferBufferContainer->activeBuffer->mapPointer + source->offset,
-            alignedRowPitch * destination->h * destination->d);
+            alignedRowPitch * blockHeight * destination->d);
 
 
         sourceLocation.pResource = temporaryBuffer->handle;
         sourceLocation.pResource = temporaryBuffer->handle;
         sourceLocation.PlacedFootprint.Offset = 0;
         sourceLocation.PlacedFootprint.Offset = 0;