Move mesa code to its own file.

This commit is contained in:
James Benton
2015-10-14 00:29:18 +01:00
parent 2bd18d0082
commit 320b522c10
6 changed files with 441 additions and 387 deletions

View File

@@ -111,6 +111,7 @@
<ClCompile Include="..\src\gpu\latte_disassembler.cpp" />
<ClCompile Include="..\src\gpu\latte_opcodes.cpp" />
<ClCompile Include="..\src\gpu\latte_tiling.cpp" />
<ClCompile Include="..\src\gpu\mesa_r600_tiling.cpp" />
<ClCompile Include="..\src\instructiontable.cpp" />
<ClCompile Include="..\src\interpreter.cpp" />
<ClCompile Include="..\src\interpreter\interpreter_branch.cpp" />
@@ -244,6 +245,7 @@
<ClInclude Include="..\src\gpu\latte.h" />
<ClInclude Include="..\src\gpu\latte_disassembler.h" />
<ClInclude Include="..\src\gpu\latte_tiling.h" />
<ClInclude Include="..\src\gpu\mesa_r600_tiling.h" />
<ClInclude Include="..\src\hostlookup.h" />
<ClInclude Include="..\src\instruction.h" />
<ClInclude Include="..\src\instructiondata.h" />

View File

@@ -531,6 +531,9 @@
<ClCompile Include="..\src\gpu\latte_analyse.cpp">
<Filter>Source Files\gpu</Filter>
</ClCompile>
<ClCompile Include="..\src\gpu\mesa_r600_tiling.cpp">
<Filter>Source Files\gpu</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\modules\coreinit\coreinit.h">
@@ -962,6 +965,9 @@
<ClInclude Include="..\src\gpu\latte_tiling.h">
<Filter>Header Files\gpu</Filter>
</ClInclude>
<ClInclude Include="..\src\gpu\mesa_r600_tiling.h">
<Filter>Header Files\gpu</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\resources\shaders\screendraw.hlsl">

View File

@@ -1,407 +1,43 @@
#include "latte_tiling.h"
#include "mesa_r600_tiling.h"
typedef int GLint;
typedef unsigned char GLubyte;
struct radeon_renderbuffer {
struct {
int Width;
int Height;
} base;
struct data {
uint8_t *ptr;
uint32_t flags;
} *bo;
bool has_surface;
int pitch;
int cpp; // byte per pixel
int group_bytes;
int num_channels; // same as pipes in r800 and above
int num_banks;
int r7xx_bank_op;
};
// Following code is derived from the legacy Mesa r600 driver (radeon_span.c).
/**************************************************************************
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#define RADEON_BO_FLAGS_MACRO_TILE 1
#define RADEON_BO_FLAGS_MICRO_TILE 2
static inline GLint r600_coord_within_microtile(GLint x, GLint y, GLint element_bytes)
void
untileSurface(GX2Surface *surface, std::vector<uint8_t> &data, uint32_t &rowPitch)
{
GLint pixel_number = 0;
switch (element_bytes) {
case 1:
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
pixel_number |= ((x >> 2) & 1) << 2; // pn[2] = x[2]
pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
pixel_number |= ((y >> 0) & 1) << 4; // pn[4] = y[0]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
break;
case 2:
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
pixel_number |= ((x >> 2) & 1) << 2; // pn[2] = x[2]
pixel_number |= ((y >> 0) & 1) << 3; // pn[3] = y[0]
pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
break;
case 4:
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
pixel_number |= ((y >> 0) & 1) << 2; // pn[2] = y[0]
pixel_number |= ((x >> 2) & 1) << 3; // pn[3] = x[2]
pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
break;
case 8:
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((y >> 0) & 1) << 1; // pn[1] = y[0]
pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
pixel_number |= ((x >> 2) & 1) << 3; // pn[3] = x[2]
pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
break;
case 16:
pixel_number |= ((y >> 0) & 1) << 0; // pn[0] = y[0]
pixel_number |= ((x >> 0) & 1) << 1; // pn[1] = x[0]
pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
pixel_number |= ((x >> 2) & 1) << 3; // pn[3] = x[2]
pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
break;
}
return pixel_number;
}
static inline GLint r600_1d_tile_helper(const struct radeon_renderbuffer * rrb,
GLint x, GLint y, GLint is_depth, GLint is_stencil)
{
GLint element_bytes = rrb->cpp;
GLint num_samples = 1;
GLint tile_width = 8;
GLint tile_height = 8;
GLint tile_thickness = 1;
GLint pitch_elements = rrb->pitch / element_bytes;
GLint height = rrb->base.Height;
GLint z = 0;
GLint sample_number = 0;
/* */
GLint tile_bytes;
GLint tiles_per_row;
GLint tiles_per_slice;
GLint slice_offset;
GLint tile_row_index;
GLint tile_column_index;
GLint tile_offset;
GLint pixel_number = 0;
GLint element_offset;
GLint offset = 0;
tile_bytes = tile_width * tile_height * tile_thickness * element_bytes * num_samples;
tiles_per_row = pitch_elements / tile_width;
tiles_per_slice = tiles_per_row * (height / tile_height);
slice_offset = (z / tile_thickness) * tiles_per_slice * tile_bytes;
tile_row_index = y / tile_height;
tile_column_index = x / tile_width;
tile_offset = ((tile_row_index * tiles_per_row) + tile_column_index) * tile_bytes;
if (is_depth) {
GLint pixel_offset = 0;
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((y >> 0) & 1) << 1; // pn[1] = y[0]
pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
pixel_number |= ((x >> 2) & 1) << 4; // pn[4] = x[2]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
switch (element_bytes) {
case 2:
pixel_offset = pixel_number * element_bytes * num_samples;
break;
case 4:
/* stencil and depth data are stored separately within a tile.
* stencil is stored in a contiguous tile before the depth tile.
* stencil element is 1 byte, depth element is 3 bytes.
* stencil tile is 64 bytes.
*/
if (is_stencil)
pixel_offset = pixel_number * 1 * num_samples;
else
pixel_offset = (pixel_number * 3 * num_samples) + 64;
break;
}
element_offset = pixel_offset + (sample_number * element_bytes);
} else {
GLint sample_offset;
pixel_number = r600_coord_within_microtile(x, y, element_bytes);
sample_offset = sample_number * (tile_bytes / num_samples);
element_offset = sample_offset + (pixel_number * element_bytes);
}
offset = slice_offset + tile_offset + element_offset;
return offset;
}
static inline GLint r600_log2(GLint n)
{
GLint log2 = 0;
while (n >>= 1)
++log2;
return log2;
}
static inline GLint r600_2d_tile_helper(const struct radeon_renderbuffer * rrb,
GLint x, GLint y, GLint is_depth, GLint is_stencil)
{
GLint group_bytes = rrb->group_bytes;
GLint num_channels = rrb->num_channels;
GLint num_banks = rrb->num_banks;
GLint r7xx_bank_op = rrb->r7xx_bank_op;
/* */
GLint group_bits = r600_log2(group_bytes);
GLint channel_bits = r600_log2(num_channels);
GLint bank_bits = r600_log2(num_banks);
GLint element_bytes = rrb->cpp;
GLint num_samples = 1;
GLint tile_width = 8;
GLint tile_height = 8;
GLint tile_thickness = 1;
GLint macro_tile_width = num_banks;
GLint macro_tile_height = num_channels;
GLint pitch_elements = (rrb->pitch / element_bytes) / tile_width;
GLint height = rrb->base.Height / tile_height;
GLint z = 0;
GLint sample_number = 0;
/* */
GLint tile_bytes;
GLint macro_tile_bytes;
GLint macro_tiles_per_row;
GLint macro_tiles_per_slice;
GLint slice_offset;
GLint macro_tile_row_index;
GLint macro_tile_column_index;
GLint macro_tile_offset;
GLint pixel_number = 0;
GLint element_offset;
GLint bank = 0;
GLint channel = 0;
GLint total_offset;
GLint group_mask = (1 << group_bits) - 1;
GLint offset_low;
GLint offset_high;
GLint offset = 0;
switch (num_channels) {
case 2:
default:
// channel[0] = x[3] ^ y[3]
channel |= (((x >> 3) ^ (y >> 3)) & 1) << 0;
break;
case 4:
// channel[0] = x[4] ^ y[3]
channel |= (((x >> 4) ^ (y >> 3)) & 1) << 0;
// channel[1] = x[3] ^ y[4]
channel |= (((x >> 3) ^ (y >> 4)) & 1) << 1;
break;
case 8:
// channel[0] = x[5] ^ y[3]
channel |= (((x >> 5) ^ (y >> 3)) & 1) << 0;
// channel[0] = x[4] ^ x[5] ^ y[4]
channel |= (((x >> 4) ^ (x >> 5) ^ (y >> 4)) & 1) << 1;
// channel[0] = x[3] ^ y[5]
channel |= (((x >> 3) ^ (y >> 5)) & 1) << 2;
break;
}
switch (num_banks) {
case 4:
// bank[0] = x[3] ^ y[4 + log2(num_channels)]
bank |= (((x >> 3) ^ (y >> (4 + channel_bits))) & 1) << 0;
if (r7xx_bank_op)
// bank[1] = x[3] ^ y[4 + log2(num_channels)] ^ x[5]
bank |= (((x >> 4) ^ (y >> (3 + channel_bits)) ^ (x >> 5)) & 1) << 1;
else
// bank[1] = x[4] ^ y[3 + log2(num_channels)]
bank |= (((x >> 4) ^ (y >> (3 + channel_bits))) & 1) << 1;
break;
case 8:
// bank[0] = x[3] ^ y[5 + log2(num_channels)]
bank |= (((x >> 3) ^ (y >> (5 + channel_bits))) & 1) << 0;
// bank[1] = x[4] ^ y[4 + log2(num_channels)] ^ y[5 + log2(num_channels)]
bank |= (((x >> 4) ^ (y >> (4 + channel_bits)) ^ (y >> (5 + channel_bits))) & 1) << 1;
if (r7xx_bank_op)
// bank[2] = x[5] ^ y[3 + log2(num_channels)] ^ x[6]
bank |= (((x >> 5) ^ (y >> (3 + channel_bits)) ^ (x >> 6)) & 1) << 2;
else
// bank[2] = x[5] ^ y[3 + log2(num_channels)]
bank |= (((x >> 5) ^ (y >> (3 + channel_bits))) & 1) << 2;
break;
}
tile_bytes = tile_width * tile_height * tile_thickness * element_bytes * num_samples;
macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;
macro_tiles_per_row = pitch_elements / macro_tile_width;
macro_tiles_per_slice = macro_tiles_per_row * (height / macro_tile_height);
slice_offset = (z / tile_thickness) * macro_tiles_per_slice * macro_tile_bytes;
macro_tile_row_index = (y / tile_height) / macro_tile_height;
macro_tile_column_index = (x / tile_width) / macro_tile_width;
macro_tile_offset = ((macro_tile_row_index * macro_tiles_per_row) + macro_tile_column_index) * macro_tile_bytes;
if (is_depth) {
GLint pixel_offset = 0;
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((y >> 0) & 1) << 1; // pn[1] = y[0]
pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
pixel_number |= ((x >> 2) & 1) << 4; // pn[4] = x[2]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
switch (element_bytes) {
case 2:
pixel_offset = pixel_number * element_bytes * num_samples;
break;
case 4:
/* stencil and depth data are stored separately within a tile.
* stencil is stored in a contiguous tile before the depth tile.
* stencil element is 1 byte, depth element is 3 bytes.
* stencil tile is 64 bytes.
*/
if (is_stencil)
pixel_offset = pixel_number * 1 * num_samples;
else
pixel_offset = (pixel_number * 3 * num_samples) + 64;
break;
}
element_offset = pixel_offset + (sample_number * element_bytes);
} else {
GLint sample_offset;
pixel_number = r600_coord_within_microtile(x, y, element_bytes);
sample_offset = sample_number * (tile_bytes / num_samples);
element_offset = sample_offset + (pixel_number * element_bytes);
}
total_offset = (slice_offset + macro_tile_offset) >> (channel_bits + bank_bits);
total_offset += element_offset;
offset_low = total_offset & group_mask;
offset_high = (total_offset & ~group_mask) << (channel_bits + bank_bits);
offset = (bank << (group_bits + channel_bits)) + (channel << group_bits) + offset_low + offset_high;
return offset;
}
/* depth buffers */
static GLubyte *r600_ptr_depth(const struct radeon_renderbuffer * rrb,
GLint x, GLint y)
{
GLubyte *ptr = rrb->bo->ptr;
GLint offset;
if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
offset = r600_2d_tile_helper(rrb, x, y, 1, 0);
else
offset = r600_1d_tile_helper(rrb, x, y, 1, 0);
return &ptr[offset];
}
static GLubyte *r600_ptr_stencil(const struct radeon_renderbuffer * rrb,
GLint x, GLint y)
{
GLubyte *ptr = rrb->bo->ptr;
GLint offset;
if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
offset = r600_2d_tile_helper(rrb, x, y, 1, 1);
else
offset = r600_1d_tile_helper(rrb, x, y, 1, 1);
return &ptr[offset];
}
static GLubyte *r600_ptr_color(const struct radeon_renderbuffer * rrb,
GLint x, GLint y)
{
GLubyte *ptr = rrb->bo->ptr;
uint32_t mask = RADEON_BO_FLAGS_MACRO_TILE | RADEON_BO_FLAGS_MICRO_TILE;
GLint offset;
if (rrb->has_surface || !(rrb->bo->flags & mask)) {
offset = x * rrb->cpp + y * rrb->pitch;
} else {
if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
offset = r600_2d_tile_helper(rrb, x, y, 0, 0);
else
offset = r600_1d_tile_helper(rrb, x, y, 0, 0);
}
return &ptr[offset];
}
// end Mesa code
#pragma pack(1)
void untileSurface(GX2Surface *surface, std::vector<uint8_t>& data, uint32_t& rowPitch) {
// TODO: This way of untiling (using expandX,expandY) will
// only work with BC compressed textures...
uint32_t cpp = 1;
auto cpp = 1;
switch (surface->format) {
case GX2SurfaceFormat::UNORM_BC1:
cpp = 8; break;
cpp = 8;
break;
case GX2SurfaceFormat::UNORM_BC3:
cpp = 16; break;
cpp = 16;
break;
default:
__debugbreak();
}
int expandX = 4;
int expandY = 4;
auto expandX = 4;
auto expandY = 4;
int surfaceWidth = (int)surface->width;
int surfaceHeight = (int)surface->height;
int surfacePitch = (int)surface->pitch;
uint8_t *surfaceData = (uint8_t*)(void*)surface->image;
uint32_t surfaceDataSize = (uint32_t)surface->imageSize;
auto surfaceWidth = (int)surface->width;
auto surfaceHeight = (int)surface->height;
auto surfacePitch = (int)surface->pitch;
auto surfaceData = reinterpret_cast<uint8_t*>(surface->image.get());
auto surfaceDataSize = surface->imageSize;
data.resize(surfaceDataSize);
radeon_renderbuffer texture;
radeon_renderbuffer::data rbdata;
mesa::radeon_renderbuffer texture;
mesa::radeon_renderbuffer::data rbdata;
texture.has_surface = false;
texture.cpp = cpp;
texture.base.Width = surfaceWidth / expandX;
texture.base.Height = surfaceHeight / expandY;
texture.pitch = surfacePitch * texture.cpp;
texture.group_bytes = 256;
switch (surface->tileMode) {
case GX2TileMode::Tiled2DThin1:
texture.num_channels = 2;
@@ -416,13 +52,14 @@ void untileSurface(GX2Surface *surface, std::vector<uint8_t>& data, uint32_t& ro
texture.bo->flags = RADEON_BO_FLAGS_MACRO_TILE;
texture.bo->ptr = surfaceData;
uint8_t* outBuf = &data[0];
auto outBuf = &data[0];
for (int y = 0; y < texture.base.Height; y++) {
for (int x = 0; x < texture.base.Width; x++) {
GLubyte *blockData = r600_ptr_color(&texture, x, y);
auto blockData = r600_ptr_color(&texture, x, y);
memcpy(outBuf + (y*texture.pitch + x*texture.cpp), blockData, texture.cpp);
}
}
rowPitch = texture.pitch;
}
}

View File

@@ -3,4 +3,4 @@
#include "systemtypes.h"
#include "modules/gx2/gx2_surface.h"
void untileSurface(GX2Surface *surface, std::vector<uint8_t>& data, uint32_t& rowPitch);
void untileSurface(GX2Surface *surface, std::vector<uint8_t> &data, uint32_t &rowPitch);

367
src/gpu/mesa_r600_tiling.cpp Executable file
View File

@@ -0,0 +1,367 @@
#include "mesa_r600_tiling.h"
typedef int GLint;
typedef unsigned char GLubyte;
// Following code is derived from the legacy Mesa r600 driver (radeon_span.c).
namespace mesa
{
/**************************************************************************
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
static inline GLint
r600_coord_within_microtile(GLint x, GLint y, GLint element_bytes)
{
GLint pixel_number = 0;
switch (element_bytes) {
case 1:
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
pixel_number |= ((x >> 2) & 1) << 2; // pn[2] = x[2]
pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
pixel_number |= ((y >> 0) & 1) << 4; // pn[4] = y[0]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
break;
case 2:
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
pixel_number |= ((x >> 2) & 1) << 2; // pn[2] = x[2]
pixel_number |= ((y >> 0) & 1) << 3; // pn[3] = y[0]
pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
break;
case 4:
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
pixel_number |= ((y >> 0) & 1) << 2; // pn[2] = y[0]
pixel_number |= ((x >> 2) & 1) << 3; // pn[3] = x[2]
pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
break;
case 8:
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((y >> 0) & 1) << 1; // pn[1] = y[0]
pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
pixel_number |= ((x >> 2) & 1) << 3; // pn[3] = x[2]
pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
break;
case 16:
pixel_number |= ((y >> 0) & 1) << 0; // pn[0] = y[0]
pixel_number |= ((x >> 0) & 1) << 1; // pn[1] = x[0]
pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
pixel_number |= ((x >> 2) & 1) << 3; // pn[3] = x[2]
pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
break;
}
return pixel_number;
}
static inline GLint
r600_1d_tile_helper(const struct radeon_renderbuffer * rrb,
GLint x, GLint y,
GLint is_depth,
GLint is_stencil)
{
GLint element_bytes = rrb->cpp;
GLint num_samples = 1;
GLint tile_width = 8;
GLint tile_height = 8;
GLint tile_thickness = 1;
GLint pitch_elements = rrb->pitch / element_bytes;
GLint height = rrb->base.Height;
GLint z = 0;
GLint sample_number = 0;
/* */
GLint tile_bytes;
GLint tiles_per_row;
GLint tiles_per_slice;
GLint slice_offset;
GLint tile_row_index;
GLint tile_column_index;
GLint tile_offset;
GLint pixel_number = 0;
GLint element_offset;
GLint offset = 0;
tile_bytes = tile_width * tile_height * tile_thickness * element_bytes * num_samples;
tiles_per_row = pitch_elements / tile_width;
tiles_per_slice = tiles_per_row * (height / tile_height);
slice_offset = (z / tile_thickness) * tiles_per_slice * tile_bytes;
tile_row_index = y / tile_height;
tile_column_index = x / tile_width;
tile_offset = ((tile_row_index * tiles_per_row) + tile_column_index) * tile_bytes;
if (is_depth) {
GLint pixel_offset = 0;
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((y >> 0) & 1) << 1; // pn[1] = y[0]
pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
pixel_number |= ((x >> 2) & 1) << 4; // pn[4] = x[2]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
switch (element_bytes) {
case 2:
pixel_offset = pixel_number * element_bytes * num_samples;
break;
case 4:
/* stencil and depth data are stored separately within a tile.
* stencil is stored in a contiguous tile before the depth tile.
* stencil element is 1 byte, depth element is 3 bytes.
* stencil tile is 64 bytes.
*/
if (is_stencil)
pixel_offset = pixel_number * 1 * num_samples;
else
pixel_offset = (pixel_number * 3 * num_samples) + 64;
break;
}
element_offset = pixel_offset + (sample_number * element_bytes);
} else {
GLint sample_offset;
pixel_number = r600_coord_within_microtile(x, y, element_bytes);
sample_offset = sample_number * (tile_bytes / num_samples);
element_offset = sample_offset + (pixel_number * element_bytes);
}
offset = slice_offset + tile_offset + element_offset;
return offset;
}
static inline GLint
r600_log2(GLint n)
{
GLint log2 = 0;
while (n >>= 1)
++log2;
return log2;
}
static inline GLint
r600_2d_tile_helper(const struct radeon_renderbuffer * rrb,
GLint x, GLint y,
GLint is_depth,
GLint is_stencil)
{
GLint group_bytes = rrb->group_bytes;
GLint num_channels = rrb->num_channels;
GLint num_banks = rrb->num_banks;
GLint r7xx_bank_op = rrb->r7xx_bank_op;
/* */
GLint group_bits = r600_log2(group_bytes);
GLint channel_bits = r600_log2(num_channels);
GLint bank_bits = r600_log2(num_banks);
GLint element_bytes = rrb->cpp;
GLint num_samples = 1;
GLint tile_width = 8;
GLint tile_height = 8;
GLint tile_thickness = 1;
GLint macro_tile_width = num_banks;
GLint macro_tile_height = num_channels;
GLint pitch_elements = (rrb->pitch / element_bytes) / tile_width;
GLint height = rrb->base.Height / tile_height;
GLint z = 0;
GLint sample_number = 0;
/* */
GLint tile_bytes;
GLint macro_tile_bytes;
GLint macro_tiles_per_row;
GLint macro_tiles_per_slice;
GLint slice_offset;
GLint macro_tile_row_index;
GLint macro_tile_column_index;
GLint macro_tile_offset;
GLint pixel_number = 0;
GLint element_offset;
GLint bank = 0;
GLint channel = 0;
GLint total_offset;
GLint group_mask = (1 << group_bits) - 1;
GLint offset_low;
GLint offset_high;
GLint offset = 0;
switch (num_channels) {
case 2:
default:
// channel[0] = x[3] ^ y[3]
channel |= (((x >> 3) ^ (y >> 3)) & 1) << 0;
break;
case 4:
// channel[0] = x[4] ^ y[3]
channel |= (((x >> 4) ^ (y >> 3)) & 1) << 0;
// channel[1] = x[3] ^ y[4]
channel |= (((x >> 3) ^ (y >> 4)) & 1) << 1;
break;
case 8:
// channel[0] = x[5] ^ y[3]
channel |= (((x >> 5) ^ (y >> 3)) & 1) << 0;
// channel[0] = x[4] ^ x[5] ^ y[4]
channel |= (((x >> 4) ^ (x >> 5) ^ (y >> 4)) & 1) << 1;
// channel[0] = x[3] ^ y[5]
channel |= (((x >> 3) ^ (y >> 5)) & 1) << 2;
break;
}
switch (num_banks) {
case 4:
// bank[0] = x[3] ^ y[4 + log2(num_channels)]
bank |= (((x >> 3) ^ (y >> (4 + channel_bits))) & 1) << 0;
if (r7xx_bank_op)
// bank[1] = x[3] ^ y[4 + log2(num_channels)] ^ x[5]
bank |= (((x >> 4) ^ (y >> (3 + channel_bits)) ^ (x >> 5)) & 1) << 1;
else
// bank[1] = x[4] ^ y[3 + log2(num_channels)]
bank |= (((x >> 4) ^ (y >> (3 + channel_bits))) & 1) << 1;
break;
case 8:
// bank[0] = x[3] ^ y[5 + log2(num_channels)]
bank |= (((x >> 3) ^ (y >> (5 + channel_bits))) & 1) << 0;
// bank[1] = x[4] ^ y[4 + log2(num_channels)] ^ y[5 + log2(num_channels)]
bank |= (((x >> 4) ^ (y >> (4 + channel_bits)) ^ (y >> (5 + channel_bits))) & 1) << 1;
if (r7xx_bank_op)
// bank[2] = x[5] ^ y[3 + log2(num_channels)] ^ x[6]
bank |= (((x >> 5) ^ (y >> (3 + channel_bits)) ^ (x >> 6)) & 1) << 2;
else
// bank[2] = x[5] ^ y[3 + log2(num_channels)]
bank |= (((x >> 5) ^ (y >> (3 + channel_bits))) & 1) << 2;
break;
}
tile_bytes = tile_width * tile_height * tile_thickness * element_bytes * num_samples;
macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;
macro_tiles_per_row = pitch_elements / macro_tile_width;
macro_tiles_per_slice = macro_tiles_per_row * (height / macro_tile_height);
slice_offset = (z / tile_thickness) * macro_tiles_per_slice * macro_tile_bytes;
macro_tile_row_index = (y / tile_height) / macro_tile_height;
macro_tile_column_index = (x / tile_width) / macro_tile_width;
macro_tile_offset = ((macro_tile_row_index * macro_tiles_per_row) + macro_tile_column_index) * macro_tile_bytes;
if (is_depth) {
GLint pixel_offset = 0;
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((y >> 0) & 1) << 1; // pn[1] = y[0]
pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
pixel_number |= ((x >> 2) & 1) << 4; // pn[4] = x[2]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
switch (element_bytes) {
case 2:
pixel_offset = pixel_number * element_bytes * num_samples;
break;
case 4:
/* stencil and depth data are stored separately within a tile.
* stencil is stored in a contiguous tile before the depth tile.
* stencil element is 1 byte, depth element is 3 bytes.
* stencil tile is 64 bytes.
*/
if (is_stencil)
pixel_offset = pixel_number * 1 * num_samples;
else
pixel_offset = (pixel_number * 3 * num_samples) + 64;
break;
}
element_offset = pixel_offset + (sample_number * element_bytes);
} else {
GLint sample_offset;
pixel_number = r600_coord_within_microtile(x, y, element_bytes);
sample_offset = sample_number * (tile_bytes / num_samples);
element_offset = sample_offset + (pixel_number * element_bytes);
}
total_offset = (slice_offset + macro_tile_offset) >> (channel_bits + bank_bits);
total_offset += element_offset;
offset_low = total_offset & group_mask;
offset_high = (total_offset & ~group_mask) << (channel_bits + bank_bits);
offset = (bank << (group_bits + channel_bits)) + (channel << group_bits) + offset_low + offset_high;
return offset;
}
uint8_t *
r600_ptr_depth(const struct radeon_renderbuffer * rrb, int x, int y)
{
GLubyte *ptr = rrb->bo->ptr;
GLint offset;
if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
offset = r600_2d_tile_helper(rrb, x, y, 1, 0);
else
offset = r600_1d_tile_helper(rrb, x, y, 1, 0);
return &ptr[offset];
}
uint8_t *
r600_ptr_stencil(const struct radeon_renderbuffer * rrb, int x, int y)
{
GLubyte *ptr = rrb->bo->ptr;
GLint offset;
if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
offset = r600_2d_tile_helper(rrb, x, y, 1, 1);
else
offset = r600_1d_tile_helper(rrb, x, y, 1, 1);
return &ptr[offset];
}
uint8_t *
r600_ptr_color(const struct radeon_renderbuffer * rrb, int x, int y)
{
GLubyte *ptr = rrb->bo->ptr;
uint32_t mask = RADEON_BO_FLAGS_MACRO_TILE | RADEON_BO_FLAGS_MICRO_TILE;
GLint offset;
if (rrb->has_surface || !(rrb->bo->flags & mask)) {
offset = x * rrb->cpp + y * rrb->pitch;
} else {
if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
offset = r600_2d_tile_helper(rrb, x, y, 0, 0);
else
offset = r600_1d_tile_helper(rrb, x, y, 0, 0);
}
return &ptr[offset];
}
} // namespace mesa

42
src/gpu/mesa_r600_tiling.h Executable file
View File

@@ -0,0 +1,42 @@
#pragma once
#include <cstdint>
#define RADEON_BO_FLAGS_MACRO_TILE 1
#define RADEON_BO_FLAGS_MICRO_TILE 2
namespace mesa
{
struct radeon_renderbuffer
{
struct
{
int Width;
int Height;
} base;
struct data
{
uint8_t *ptr;
uint32_t flags;
} *bo;
bool has_surface;
int pitch;
int cpp; // byte per pixel
int group_bytes;
int num_channels; // same as pipes in r800 and above
int num_banks;
int r7xx_bank_op;
};
uint8_t *
r600_ptr_depth(const struct radeon_renderbuffer * rrb, int x, int y);
uint8_t *
r600_ptr_stencil(const struct radeon_renderbuffer * rrb, int x, int y);
uint8_t *
r600_ptr_color(const struct radeon_renderbuffer * rrb, int x, int y);
} // namespace mesa