blob: 86a5d4b50b743907e9254dfddde69cc51865916e [file] [log] [blame]
/*
* XGL
*
* Copyright (C) 2014 LunarG, Inc.
*
* 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 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 AUTHORS OR COPYRIGHT HOLDERS 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:
* LunarG
*/
#include "gpu.h"
#include "pipeline.h"
#include "compiler/shader/compiler_interface.h"
#include "compiler/pipeline/pipeline_compiler_interface.h"
#include "compiler/pipeline/brw_blorp_blit_eu.h"
#include "compiler/pipeline/brw_blorp.h"
class intel_meta_compiler : public brw_blorp_eu_emitter
{
public:
intel_meta_compiler(struct brw_context *brw,
enum intel_dev_meta_shader id);
void *compile(brw_blorp_prog_data *prog_data, uint32_t *code_size);
private:
void alloc_regs();
void alloc_pcb_regs(int grf);
void emit_compute_frag_coord();
void emit_copy_mem();
void emit_clear_color();
void emit_clear_depth();
void *codegen(uint32_t *code_size);
struct brw_context *brw;
enum intel_dev_meta_shader id;
const struct brw_reg poison;
const struct brw_reg r0;
const struct brw_reg r1;
const int base_grf;
const int base_mrf;
struct brw_reg clear_vals[4];
struct brw_reg src_offset_x;
struct brw_reg src_offset_y;
struct brw_reg src_layer;
struct brw_reg src_lod;
struct brw_reg dst_mem_offset;
struct brw_reg dst_extent_width;
struct brw_reg frag_x;
struct brw_reg frag_y;
struct brw_reg texels[4];
struct brw_reg tmp1;
struct brw_reg tmp2;
};
intel_meta_compiler::intel_meta_compiler(struct brw_context *brw,
enum intel_dev_meta_shader id)
: brw_blorp_eu_emitter(brw), brw(brw), id(id),
poison(brw_imm_ud(0x12345678)),
r0(retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW)),
r1(retype(brw_vec8_grf(1, 0), BRW_REGISTER_TYPE_UW)),
base_grf(2), /* skipping r0 and r1 */
base_mrf(2)
{
int i;
for (i = 0; i < ARRAY_SIZE(clear_vals); i++)
clear_vals[i] = poison;
src_offset_x = poison;
src_offset_y = poison;
src_layer = poison;
src_lod = poison;
dst_mem_offset = poison;
dst_extent_width = poison;
}
void intel_meta_compiler::alloc_pcb_regs(int grf)
{
/* clears are special */
switch (id) {
case INTEL_DEV_META_FS_CLEAR_COLOR:
case INTEL_DEV_META_FS_CLEAR_DEPTH:
clear_vals[0] = retype(brw_vec1_grf(grf, 0), BRW_REGISTER_TYPE_UD);
clear_vals[1] = retype(brw_vec1_grf(grf, 1), BRW_REGISTER_TYPE_UD);
clear_vals[2] = retype(brw_vec1_grf(grf, 2), BRW_REGISTER_TYPE_UD);
clear_vals[3] = retype(brw_vec1_grf(grf, 3), BRW_REGISTER_TYPE_UD);
return;
default:
break;
}
src_offset_x = retype(brw_vec1_grf(grf, 0), BRW_REGISTER_TYPE_UD);
src_offset_y = retype(brw_vec1_grf(grf, 1), BRW_REGISTER_TYPE_UD);
switch (id) {
case INTEL_DEV_META_FS_COPY_MEM:
case INTEL_DEV_META_FS_COPY_1D:
case INTEL_DEV_META_FS_COPY_1D_ARRAY:
case INTEL_DEV_META_FS_COPY_2D:
case INTEL_DEV_META_FS_COPY_2D_ARRAY:
case INTEL_DEV_META_FS_COPY_2D_MS:
src_layer = retype(brw_vec1_grf(grf, 2), BRW_REGISTER_TYPE_UD);
src_lod = retype(brw_vec1_grf(grf, 3), BRW_REGISTER_TYPE_UD);
break;
case INTEL_DEV_META_FS_COPY_1D_TO_MEM:
case INTEL_DEV_META_FS_COPY_1D_ARRAY_TO_MEM:
case INTEL_DEV_META_FS_COPY_2D_TO_MEM:
case INTEL_DEV_META_FS_COPY_2D_ARRAY_TO_MEM:
case INTEL_DEV_META_FS_COPY_2D_MS_TO_MEM:
src_layer = retype(brw_vec1_grf(grf, 2), BRW_REGISTER_TYPE_UD);
src_lod = retype(brw_vec1_grf(grf, 3), BRW_REGISTER_TYPE_UD);
dst_mem_offset = retype(brw_vec1_grf(grf, 4), BRW_REGISTER_TYPE_UD);
dst_extent_width = retype(brw_vec1_grf(grf, 5), BRW_REGISTER_TYPE_UD);
break;
case INTEL_DEV_META_FS_COPY_MEM_TO_IMG:
dst_extent_width = retype(brw_vec1_grf(grf, 2), BRW_REGISTER_TYPE_UD);
break;
case INTEL_DEV_META_FS_RESOLVE_2X:
case INTEL_DEV_META_FS_RESOLVE_4X:
case INTEL_DEV_META_FS_RESOLVE_8X:
case INTEL_DEV_META_FS_RESOLVE_16X:
break;
default:
break;
}
}
void intel_meta_compiler::alloc_regs(void)
{
int grf = base_grf;
int i;
alloc_pcb_regs(grf);
grf++;
frag_x = retype(brw_vec8_grf(grf, 0), BRW_REGISTER_TYPE_UD);
grf += 2;
frag_y = retype(brw_vec8_grf(grf, 0), BRW_REGISTER_TYPE_UD);
grf += 2;
for (i = 0; i < ARRAY_SIZE(texels); i++) {
texels[i] = retype(vec16(brw_vec8_grf(grf, 0)), BRW_REGISTER_TYPE_UD);
grf += 8;
}
tmp1 = retype(brw_vec8_grf(grf, 0), BRW_REGISTER_TYPE_UD);
grf += 2;
tmp2 = retype(brw_vec8_grf(grf, 0), BRW_REGISTER_TYPE_UD);
grf += 2;
}
void intel_meta_compiler::emit_compute_frag_coord()
{
emit_add(vec16(retype(frag_x, BRW_REGISTER_TYPE_UW)),
stride(suboffset(r1, 4), 2, 4, 0), brw_imm_v(0x10101010));
emit_add(vec16(retype(frag_y, BRW_REGISTER_TYPE_UW)),
stride(suboffset(r1, 5), 2, 4, 0), brw_imm_v(0x11001100));
}
void intel_meta_compiler::emit_copy_mem()
{
struct brw_reg mrf = retype(vec16(brw_message_reg(base_mrf)),
BRW_REGISTER_TYPE_UD);
int mrf_offset = 0;
int i;
emit_compute_frag_coord();
emit_add(offset(mrf, mrf_offset),
retype(frag_x, BRW_REGISTER_TYPE_UW),
retype(src_offset_x, BRW_REGISTER_TYPE_UW));
mrf_offset += 2;
emit_texture_lookup(texels[0], SHADER_OPCODE_TXF, base_mrf, mrf_offset);
mrf_offset = 0;
for (i = 0; i < 4; i++) {
emit_mov(offset(mrf, mrf_offset), offset(texels[0], i * 2));
mrf_offset += 2;
}
emit_render_target_write(mrf, base_mrf, mrf_offset, false);
}
void intel_meta_compiler::emit_clear_color()
{
struct brw_reg mrf = retype(vec16(brw_message_reg(base_mrf)),
BRW_REGISTER_TYPE_UD);
int mrf_offset = 0;
int i;
for (i = 0; i < 4; i++) {
emit_mov(offset(mrf, mrf_offset), clear_vals[i]);
mrf_offset += 2;
}
emit_render_target_write(mrf, base_mrf, mrf_offset, false);
}
void intel_meta_compiler::emit_clear_depth()
{
struct brw_reg mrf = retype(vec16(brw_message_reg(base_mrf)),
BRW_REGISTER_TYPE_UD);
/* skip colors */
int mrf_offset = 4 * 2;
/* oDepth */
emit_mov(offset(mrf, mrf_offset), clear_vals[0]);
mrf_offset += 2;
emit_render_target_write(mrf, base_mrf, mrf_offset, false);
}
void *intel_meta_compiler::codegen(uint32_t *code_size)
{
const unsigned *prog;
unsigned prog_size;
void *code;
prog = get_program(&prog_size, stderr);
code = icd_alloc(prog_size, 0, XGL_SYSTEM_ALLOC_INTERNAL);
if (!code)
return NULL;
memcpy(code, prog, prog_size);
if (code_size)
*code_size = prog_size;
return code;
}
void *intel_meta_compiler::compile(brw_blorp_prog_data *prog_data,
uint32_t *code_size)
{
memset(prog_data, 0, sizeof(*prog_data));
prog_data->first_curbe_grf = base_grf;
alloc_regs();
switch (id) {
case INTEL_DEV_META_FS_COPY_MEM:
emit_copy_mem();
break;
case INTEL_DEV_META_FS_COPY_1D:
case INTEL_DEV_META_FS_COPY_1D_ARRAY:
case INTEL_DEV_META_FS_COPY_2D:
case INTEL_DEV_META_FS_COPY_2D_ARRAY:
case INTEL_DEV_META_FS_COPY_2D_MS:
emit_clear_color();
break;
case INTEL_DEV_META_FS_COPY_1D_TO_MEM:
case INTEL_DEV_META_FS_COPY_1D_ARRAY_TO_MEM:
case INTEL_DEV_META_FS_COPY_2D_TO_MEM:
case INTEL_DEV_META_FS_COPY_2D_ARRAY_TO_MEM:
case INTEL_DEV_META_FS_COPY_2D_MS_TO_MEM:
emit_clear_color();
break;
case INTEL_DEV_META_FS_COPY_MEM_TO_IMG:
emit_clear_color();
break;
case INTEL_DEV_META_FS_CLEAR_COLOR:
emit_clear_color();
break;
case INTEL_DEV_META_FS_CLEAR_DEPTH:
emit_clear_depth();
break;
case INTEL_DEV_META_FS_RESOLVE_2X:
case INTEL_DEV_META_FS_RESOLVE_4X:
case INTEL_DEV_META_FS_RESOLVE_8X:
case INTEL_DEV_META_FS_RESOLVE_16X:
emit_clear_color();
break;
default:
emit_clear_color();
break;
}
return codegen(code_size);
}
extern "C" {
XGL_RESULT intel_pipeline_shader_compile_meta(struct intel_pipeline_shader *sh,
const struct intel_gpu *gpu,
enum intel_dev_meta_shader id)
{
struct brw_context *brw = intel_create_brw_context(gpu);
intel_meta_compiler c(brw, id);
brw_blorp_prog_data prog_data;
sh->pCode = c.compile(&prog_data, &sh->codeSize);
sh->out_count = 1;
sh->surface_count = BRW_BLORP_NUM_BINDING_TABLE_ENTRIES;
sh->urb_grf_start = prog_data.first_curbe_grf;
switch (id) {
case INTEL_DEV_META_FS_CLEAR_DEPTH:
sh->uses = INTEL_SHADER_USE_COMPUTED_DEPTH;
break;
default:
sh->uses = 0;
break;
}
ralloc_free(brw);
return (sh->pCode) ? XGL_SUCCESS : XGL_ERROR_UNKNOWN;
}
} // extern "C"