diff options
author | Dave Airlie <airlied@redhat.com> | 2012-12-16 10:31:32 +0000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-01-11 22:31:54 +0000 |
commit | d23aa650015ec017649f5a4ce8cb12d8c314bd3a (patch) | |
tree | a76e70719be1969b929be5f96bc8f6993bfc653f | |
parent | 77c10225eef43eb428ebbc80f1dd426e3d33b281 (diff) |
r600g: texture buffer object + glsl 1.40 enable support (v2)
This adds TBO support to r600g, and with GLSL 1.40 enabled,
we now get 3.1 core profiles advertised for r600g.
The r600/700 implementation is a bit different from the evergreen one,
as r6/7 hw lacks vertex fetch swizzles. So we implement it by passing 5
constants per sampler to the shader, the shader uses the first 4 as masks
for each component and the 5th as the alpha value to OR in.
Now TXQ is also broken so we have to pass a constant for the buffer size,
on evergreen we just pass this, on r6/7 we pass it as the 6th element
in the const info buffer.
v1.1: drop return as DDX doesn't use a texture type
v2: add r600/700 support.
Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r-- | src/gallium/drivers/r600/evergreen_state.c | 55 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_asm.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_asm.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.c | 4 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.h | 10 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_shader.c | 134 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_shader.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_state.c | 43 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_state_common.c | 125 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_texture.c | 16 |
10 files changed, 373 insertions, 19 deletions
diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index d0402c219fb..7040b7aa8cb 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c | |||
@@ -969,6 +969,58 @@ static void *evergreen_create_sampler_state(struct pipe_context *ctx, | |||
969 | return ss; | 969 | return ss; |
970 | } | 970 | } |
971 | 971 | ||
972 | static struct pipe_sampler_view * | ||
973 | texture_buffer_sampler_view(struct r600_pipe_sampler_view *view, | ||
974 | unsigned width0, unsigned height0) | ||
975 | |||
976 | { | ||
977 | struct pipe_context *ctx = view->base.context; | ||
978 | struct r600_texture *tmp = (struct r600_texture*)view->base.texture; | ||
979 | uint64_t va; | ||
980 | int stride = util_format_get_blocksize(view->base.format); | ||
981 | unsigned format, num_format, format_comp, endian; | ||
982 | unsigned swizzle_res; | ||
983 | unsigned char swizzle[4]; | ||
984 | const struct util_format_description *desc; | ||
985 | |||
986 | swizzle[0] = view->base.swizzle_r; | ||
987 | swizzle[1] = view->base.swizzle_g; | ||
988 | swizzle[2] = view->base.swizzle_b; | ||
989 | swizzle[3] = view->base.swizzle_a; | ||
990 | |||
991 | r600_vertex_data_type(view->base.format, | ||
992 | &format, &num_format, &format_comp, | ||
993 | &endian); | ||
994 | |||
995 | desc = util_format_description(view->base.format); | ||
996 | |||
997 | swizzle_res = r600_get_swizzle_combined(desc->swizzle, swizzle, TRUE); | ||
998 | |||
999 | va = r600_resource_va(ctx->screen, view->base.texture); | ||
1000 | view->tex_resource = &tmp->resource; | ||
1001 | |||
1002 | view->skip_mip_address_reloc = true; | ||
1003 | view->tex_resource_words[0] = va; | ||
1004 | view->tex_resource_words[1] = width0 - 1; | ||
1005 | view->tex_resource_words[2] = S_030008_BASE_ADDRESS_HI(va >> 32UL) | | ||
1006 | S_030008_STRIDE(stride) | | ||
1007 | S_030008_DATA_FORMAT(format) | | ||
1008 | S_030008_NUM_FORMAT_ALL(num_format) | | ||
1009 | S_030008_FORMAT_COMP_ALL(format_comp) | | ||
1010 | S_030008_SRF_MODE_ALL(1) | | ||
1011 | S_030008_ENDIAN_SWAP(endian); | ||
1012 | view->tex_resource_words[3] = swizzle_res; | ||
1013 | /* | ||
1014 | * in theory dword 4 is for number of elements, for use with resinfo, | ||
1015 | * but it seems to utterly fail to work, the amd gpu shader analyser | ||
1016 | * uses a const buffer to store the element sizes for buffer txq | ||
1017 | */ | ||
1018 | view->tex_resource_words[4] = 0; | ||
1019 | view->tex_resource_words[5] = view->tex_resource_words[6] = 0; | ||
1020 | view->tex_resource_words[7] = S_03001C_TYPE(V_03001C_SQ_TEX_VTX_VALID_BUFFER); | ||
1021 | return &view->base; | ||
1022 | } | ||
1023 | |||
972 | struct pipe_sampler_view * | 1024 | struct pipe_sampler_view * |
973 | evergreen_create_sampler_view_custom(struct pipe_context *ctx, | 1025 | evergreen_create_sampler_view_custom(struct pipe_context *ctx, |
974 | struct pipe_resource *texture, | 1026 | struct pipe_resource *texture, |
@@ -997,6 +1049,9 @@ evergreen_create_sampler_view_custom(struct pipe_context *ctx, | |||
997 | view->base.reference.count = 1; | 1049 | view->base.reference.count = 1; |
998 | view->base.context = ctx; | 1050 | view->base.context = ctx; |
999 | 1051 | ||
1052 | if (texture->target == PIPE_BUFFER) | ||
1053 | return texture_buffer_sampler_view(view, width0, height0); | ||
1054 | |||
1000 | swizzle[0] = state->swizzle_r; | 1055 | swizzle[0] = state->swizzle_r; |
1001 | swizzle[1] = state->swizzle_g; | 1056 | swizzle[1] = state->swizzle_g; |
1002 | swizzle[2] = state->swizzle_b; | 1057 | swizzle[2] = state->swizzle_b; |
diff --git a/src/gallium/drivers/r600/r600_asm.c b/src/gallium/drivers/r600/r600_asm.c index d324d59f48d..0a6f63ff9c0 100644 --- a/src/gallium/drivers/r600/r600_asm.c +++ b/src/gallium/drivers/r600/r600_asm.c | |||
@@ -2609,7 +2609,7 @@ void r600_bytecode_dump(struct r600_bytecode *bc) | |||
2609 | fprintf(stderr, "--------------------------------------\n"); | 2609 | fprintf(stderr, "--------------------------------------\n"); |
2610 | } | 2610 | } |
2611 | 2611 | ||
2612 | static void r600_vertex_data_type(enum pipe_format pformat, | 2612 | void r600_vertex_data_type(enum pipe_format pformat, |
2613 | unsigned *format, | 2613 | unsigned *format, |
2614 | unsigned *num_format, unsigned *format_comp, unsigned *endian) | 2614 | unsigned *num_format, unsigned *format_comp, unsigned *endian) |
2615 | { | 2615 | { |
diff --git a/src/gallium/drivers/r600/r600_asm.h b/src/gallium/drivers/r600/r600_asm.h index 5727a7c421f..182f403aa77 100644 --- a/src/gallium/drivers/r600/r600_asm.h +++ b/src/gallium/drivers/r600/r600_asm.h | |||
@@ -250,4 +250,6 @@ void r700_bytecode_alu_read(struct r600_bytecode_alu *alu, uint32_t word0, uint3 | |||
250 | void r600_bytecode_export_read(struct r600_bytecode_output *output, uint32_t word0, uint32_t word1); | 250 | void r600_bytecode_export_read(struct r600_bytecode_output *output, uint32_t word0, uint32_t word1); |
251 | void eg_bytecode_export_read(struct r600_bytecode_output *output, uint32_t word0, uint32_t word1); | 251 | void eg_bytecode_export_read(struct r600_bytecode_output *output, uint32_t word0, uint32_t word1); |
252 | 252 | ||
253 | void r600_vertex_data_type(enum pipe_format pformat, unsigned *format, | ||
254 | unsigned *num_format, unsigned *format_comp, unsigned *endian); | ||
253 | #endif | 255 | #endif |
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 29ef988372b..92beabc74d0 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c | |||
@@ -416,6 +416,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) | |||
416 | case PIPE_CAP_COMPUTE: | 416 | case PIPE_CAP_COMPUTE: |
417 | case PIPE_CAP_START_INSTANCE: | 417 | case PIPE_CAP_START_INSTANCE: |
418 | case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: | 418 | case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: |
419 | case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: | ||
419 | return 1; | 420 | return 1; |
420 | 421 | ||
421 | case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: | 422 | case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: |
@@ -425,7 +426,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) | |||
425 | return 256; | 426 | return 256; |
426 | 427 | ||
427 | case PIPE_CAP_GLSL_FEATURE_LEVEL: | 428 | case PIPE_CAP_GLSL_FEATURE_LEVEL: |
428 | return 130; | 429 | return 140; |
429 | 430 | ||
430 | case PIPE_CAP_TEXTURE_MULTISAMPLE: | 431 | case PIPE_CAP_TEXTURE_MULTISAMPLE: |
431 | return rscreen->msaa_texture_support != MSAA_TEXTURE_SAMPLE_ZERO; | 432 | return rscreen->msaa_texture_support != MSAA_TEXTURE_SAMPLE_ZERO; |
@@ -450,7 +451,6 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) | |||
450 | case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: | 451 | case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: |
451 | case PIPE_CAP_VERTEX_COLOR_CLAMPED: | 452 | case PIPE_CAP_VERTEX_COLOR_CLAMPED: |
452 | case PIPE_CAP_USER_VERTEX_BUFFERS: | 453 | case PIPE_CAP_USER_VERTEX_BUFFERS: |
453 | case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: | ||
454 | return 0; | 454 | return 0; |
455 | 455 | ||
456 | /* Stream output. */ | 456 | /* Stream output. */ |
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 2dcb4734e6b..d983718b1bb 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h | |||
@@ -40,12 +40,13 @@ | |||
40 | #define R600_TRACE_CS 0 | 40 | #define R600_TRACE_CS 0 |
41 | 41 | ||
42 | #define R600_MAX_USER_CONST_BUFFERS 13 | 42 | #define R600_MAX_USER_CONST_BUFFERS 13 |
43 | #define R600_MAX_DRIVER_CONST_BUFFERS 2 | 43 | #define R600_MAX_DRIVER_CONST_BUFFERS 3 |
44 | #define R600_MAX_CONST_BUFFERS (R600_MAX_USER_CONST_BUFFERS + R600_MAX_DRIVER_CONST_BUFFERS) | 44 | #define R600_MAX_CONST_BUFFERS (R600_MAX_USER_CONST_BUFFERS + R600_MAX_DRIVER_CONST_BUFFERS) |
45 | 45 | ||
46 | /* start driver buffers after user buffers */ | 46 | /* start driver buffers after user buffers */ |
47 | #define R600_UCP_CONST_BUFFER (R600_MAX_USER_CONST_BUFFERS) | 47 | #define R600_UCP_CONST_BUFFER (R600_MAX_USER_CONST_BUFFERS) |
48 | #define R600_TXQ_CONST_BUFFER (R600_MAX_USER_CONST_BUFFERS + 1) | 48 | #define R600_TXQ_CONST_BUFFER (R600_MAX_USER_CONST_BUFFERS + 1) |
49 | #define R600_BUFFER_INFO_CONST_BUFFER (R600_MAX_USER_CONST_BUFFERS + 2) | ||
49 | 50 | ||
50 | #define R600_MAX_CONST_BUFFER_SIZE 4096 | 51 | #define R600_MAX_CONST_BUFFER_SIZE 4096 |
51 | 52 | ||
@@ -330,6 +331,7 @@ struct r600_samplerview_state { | |||
330 | uint32_t compressed_depthtex_mask; /* which textures are depth */ | 331 | uint32_t compressed_depthtex_mask; /* which textures are depth */ |
331 | uint32_t compressed_colortex_mask; | 332 | uint32_t compressed_colortex_mask; |
332 | boolean dirty_txq_constants; | 333 | boolean dirty_txq_constants; |
334 | boolean dirty_buffer_constants; | ||
333 | }; | 335 | }; |
334 | 336 | ||
335 | struct r600_sampler_states { | 337 | struct r600_sampler_states { |
@@ -347,6 +349,8 @@ struct r600_textures_info { | |||
347 | 349 | ||
348 | /* cube array txq workaround */ | 350 | /* cube array txq workaround */ |
349 | uint32_t *txq_constants; | 351 | uint32_t *txq_constants; |
352 | /* buffer related workarounds */ | ||
353 | uint32_t *buffer_constants; | ||
350 | }; | 354 | }; |
351 | 355 | ||
352 | struct r600_fence { | 356 | struct r600_fence { |
@@ -678,6 +682,10 @@ struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe, | |||
678 | const struct pipe_surface *templ, | 682 | const struct pipe_surface *templ, |
679 | unsigned width, unsigned height); | 683 | unsigned width, unsigned height); |
680 | 684 | ||
685 | unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format, | ||
686 | const unsigned char *swizzle_view, | ||
687 | boolean vtx); | ||
688 | |||
681 | /* r600_state_common.c */ | 689 | /* r600_state_common.c */ |
682 | void r600_init_common_state_functions(struct r600_context *rctx); | 690 | void r600_init_common_state_functions(struct r600_context *rctx); |
683 | void r600_emit_cso_state(struct r600_context *rctx, struct r600_atom *atom); | 691 | void r600_emit_cso_state(struct r600_context *rctx, struct r600_atom *atom); |
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index e0c2b44b5b1..83077504385 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c | |||
@@ -3896,6 +3896,128 @@ static inline unsigned tgsi_tex_get_src_gpr(struct r600_shader_ctx *ctx, | |||
3896 | return ctx->file_offset[inst->Src[index].Register.File] + inst->Src[index].Register.Index; | 3896 | return ctx->file_offset[inst->Src[index].Register.File] + inst->Src[index].Register.Index; |
3897 | } | 3897 | } |
3898 | 3898 | ||
3899 | static int do_vtx_fetch_inst(struct r600_shader_ctx *ctx, boolean src_requires_loading) | ||
3900 | { | ||
3901 | struct r600_bytecode_vtx vtx; | ||
3902 | struct r600_bytecode_alu alu; | ||
3903 | struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; | ||
3904 | int src_gpr, r, i; | ||
3905 | int id = tgsi_tex_get_src_gpr(ctx, 1); | ||
3906 | |||
3907 | src_gpr = tgsi_tex_get_src_gpr(ctx, 0); | ||
3908 | if (src_requires_loading) { | ||
3909 | for (i = 0; i < 4; i++) { | ||
3910 | memset(&alu, 0, sizeof(struct r600_bytecode_alu)); | ||
3911 | alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); | ||
3912 | r600_bytecode_src(&alu.src[0], &ctx->src[0], i); | ||
3913 | alu.dst.sel = ctx->temp_reg; | ||
3914 | alu.dst.chan = i; | ||
3915 | if (i == 3) | ||
3916 | alu.last = 1; | ||
3917 | alu.dst.write = 1; | ||
3918 | r = r600_bytecode_add_alu(ctx->bc, &alu); | ||
3919 | if (r) | ||
3920 | return r; | ||
3921 | } | ||
3922 | src_gpr = ctx->temp_reg; | ||
3923 | } | ||
3924 | |||
3925 | memset(&vtx, 0, sizeof(vtx)); | ||
3926 | vtx.inst = 0; | ||
3927 | vtx.buffer_id = id + R600_MAX_CONST_BUFFERS; | ||
3928 | vtx.fetch_type = 2; /* VTX_FETCH_NO_INDEX_OFFSET */ | ||
3929 | vtx.src_gpr = src_gpr; | ||
3930 | vtx.mega_fetch_count = 16; | ||
3931 | vtx.dst_gpr = ctx->file_offset[inst->Dst[0].Register.File] + inst->Dst[0].Register.Index; | ||
3932 | vtx.dst_sel_x = (inst->Dst[0].Register.WriteMask & 1) ? 0 : 7; /* SEL_X */ | ||
3933 | vtx.dst_sel_y = (inst->Dst[0].Register.WriteMask & 2) ? 1 : 7; /* SEL_Y */ | ||
3934 | vtx.dst_sel_z = (inst->Dst[0].Register.WriteMask & 4) ? 2 : 7; /* SEL_Z */ | ||
3935 | vtx.dst_sel_w = (inst->Dst[0].Register.WriteMask & 8) ? 3 : 7; /* SEL_W */ | ||
3936 | vtx.use_const_fields = 1; | ||
3937 | vtx.srf_mode_all = 1; /* SRF_MODE_NO_ZERO */ | ||
3938 | |||
3939 | if ((r = r600_bytecode_add_vtx(ctx->bc, &vtx))) | ||
3940 | return r; | ||
3941 | |||
3942 | if (ctx->bc->chip_class >= EVERGREEN) | ||
3943 | return 0; | ||
3944 | |||
3945 | for (i = 0; i < 4; i++) { | ||
3946 | int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask); | ||
3947 | if (!(inst->Dst[0].Register.WriteMask & (1 << i))) | ||
3948 | continue; | ||
3949 | |||
3950 | memset(&alu, 0, sizeof(struct r600_bytecode_alu)); | ||
3951 | alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_AND_INT); | ||
3952 | |||
3953 | alu.dst.chan = i; | ||
3954 | alu.dst.sel = vtx.dst_gpr; | ||
3955 | alu.dst.write = 1; | ||
3956 | |||
3957 | alu.src[0].sel = vtx.dst_gpr; | ||
3958 | alu.src[0].chan = i; | ||
3959 | |||
3960 | alu.src[1].sel = 512 + (id * 2); | ||
3961 | alu.src[1].chan = i % 4; | ||
3962 | alu.src[1].kc_bank = R600_BUFFER_INFO_CONST_BUFFER; | ||
3963 | |||
3964 | if (i == lasti) | ||
3965 | alu.last = 1; | ||
3966 | r = r600_bytecode_add_alu(ctx->bc, &alu); | ||
3967 | if (r) | ||
3968 | return r; | ||
3969 | } | ||
3970 | |||
3971 | if (inst->Dst[0].Register.WriteMask & 3) { | ||
3972 | memset(&alu, 0, sizeof(struct r600_bytecode_alu)); | ||
3973 | alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_OR_INT); | ||
3974 | |||
3975 | alu.dst.chan = 3; | ||
3976 | alu.dst.sel = vtx.dst_gpr; | ||
3977 | alu.dst.write = 1; | ||
3978 | |||
3979 | alu.src[0].sel = vtx.dst_gpr; | ||
3980 | alu.src[0].chan = 3; | ||
3981 | |||
3982 | alu.src[1].sel = 512 + (id * 2) + 1; | ||
3983 | alu.src[1].chan = 0; | ||
3984 | alu.src[1].kc_bank = R600_BUFFER_INFO_CONST_BUFFER; | ||
3985 | |||
3986 | alu.last = 1; | ||
3987 | r = r600_bytecode_add_alu(ctx->bc, &alu); | ||
3988 | if (r) | ||
3989 | return r; | ||
3990 | } | ||
3991 | return 0; | ||
3992 | } | ||
3993 | |||
3994 | static int r600_do_buffer_txq(struct r600_shader_ctx *ctx) | ||
3995 | { | ||
3996 | struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; | ||
3997 | struct r600_bytecode_alu alu; | ||
3998 | int r; | ||
3999 | int id = tgsi_tex_get_src_gpr(ctx, 1); | ||
4000 | |||
4001 | memset(&alu, 0, sizeof(struct r600_bytecode_alu)); | ||
4002 | alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); | ||
4003 | |||
4004 | if (ctx->bc->chip_class >= EVERGREEN) { | ||
4005 | alu.src[0].sel = 512 + (id / 4); | ||
4006 | alu.src[0].chan = id % 4; | ||
4007 | } else { | ||
4008 | /* r600 we have them at channel 2 of the second dword */ | ||
4009 | alu.src[0].sel = 512 + (id * 2) + 1; | ||
4010 | alu.src[0].chan = 1; | ||
4011 | } | ||
4012 | alu.src[0].kc_bank = R600_BUFFER_INFO_CONST_BUFFER; | ||
4013 | tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst); | ||
4014 | alu.last = 1; | ||
4015 | r = r600_bytecode_add_alu(ctx->bc, &alu); | ||
4016 | if (r) | ||
4017 | return r; | ||
4018 | return 0; | ||
4019 | } | ||
4020 | |||
3899 | static int tgsi_tex(struct r600_shader_ctx *ctx) | 4021 | static int tgsi_tex(struct r600_shader_ctx *ctx) |
3900 | { | 4022 | { |
3901 | static float one_point_five = 1.5f; | 4023 | static float one_point_five = 1.5f; |
@@ -3934,6 +4056,18 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) | |||
3934 | 4056 | ||
3935 | src_gpr = tgsi_tex_get_src_gpr(ctx, 0); | 4057 | src_gpr = tgsi_tex_get_src_gpr(ctx, 0); |
3936 | 4058 | ||
4059 | if (inst->Texture.Texture == TGSI_TEXTURE_BUFFER) { | ||
4060 | if (inst->Instruction.Opcode == TGSI_OPCODE_TXQ) { | ||
4061 | ctx->shader->uses_tex_buffers = true; | ||
4062 | return r600_do_buffer_txq(ctx); | ||
4063 | } | ||
4064 | else if (inst->Instruction.Opcode == TGSI_OPCODE_TXF) { | ||
4065 | if (ctx->bc->chip_class < EVERGREEN) | ||
4066 | ctx->shader->uses_tex_buffers = true; | ||
4067 | return do_vtx_fetch_inst(ctx, src_requires_loading); | ||
4068 | } | ||
4069 | } | ||
4070 | |||
3937 | if (inst->Instruction.Opcode == TGSI_OPCODE_TXF) { | 4071 | if (inst->Instruction.Opcode == TGSI_OPCODE_TXF) { |
3938 | /* get offset values */ | 4072 | /* get offset values */ |
3939 | if (inst->Texture.NumOffsets) { | 4073 | if (inst->Texture.NumOffsets) { |
diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h index b58a58ab4db..d61efcb1a72 100644 --- a/src/gallium/drivers/r600/r600_shader.h +++ b/src/gallium/drivers/r600/r600_shader.h | |||
@@ -61,6 +61,7 @@ struct r600_shader { | |||
61 | boolean vs_out_misc_write; | 61 | boolean vs_out_misc_write; |
62 | boolean vs_out_point_size; | 62 | boolean vs_out_point_size; |
63 | boolean has_txq_cube_array_z_comp; | 63 | boolean has_txq_cube_array_z_comp; |
64 | boolean uses_tex_buffers; | ||
64 | }; | 65 | }; |
65 | 66 | ||
66 | struct r600_shader_key { | 67 | struct r600_shader_key { |
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index e2d0f7544c1..17c5a64e9e7 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c | |||
@@ -976,6 +976,46 @@ static void *r600_create_sampler_state(struct pipe_context *ctx, | |||
976 | return ss; | 976 | return ss; |
977 | } | 977 | } |
978 | 978 | ||
979 | static struct pipe_sampler_view * | ||
980 | texture_buffer_sampler_view(struct r600_pipe_sampler_view *view, | ||
981 | unsigned width0, unsigned height0) | ||
982 | |||
983 | { | ||
984 | struct pipe_context *ctx = view->base.context; | ||
985 | struct r600_texture *tmp = (struct r600_texture*)view->base.texture; | ||
986 | uint64_t va; | ||
987 | int stride = util_format_get_blocksize(view->base.format); | ||
988 | unsigned format, num_format, format_comp, endian; | ||
989 | |||
990 | r600_vertex_data_type(view->base.format, | ||
991 | &format, &num_format, &format_comp, | ||
992 | &endian); | ||
993 | |||
994 | va = r600_resource_va(ctx->screen, view->base.texture); | ||
995 | view->tex_resource = &tmp->resource; | ||
996 | |||
997 | view->skip_mip_address_reloc = true; | ||
998 | view->tex_resource_words[0] = va; | ||
999 | view->tex_resource_words[1] = width0 - 1; | ||
1000 | view->tex_resource_words[2] = S_038008_BASE_ADDRESS_HI(va >> 32UL) | | ||
1001 | S_038008_STRIDE(stride) | | ||
1002 | S_038008_DATA_FORMAT(format) | | ||
1003 | S_038008_NUM_FORMAT_ALL(num_format) | | ||
1004 | S_038008_FORMAT_COMP_ALL(format_comp) | | ||
1005 | S_038008_SRF_MODE_ALL(1) | | ||
1006 | S_038008_ENDIAN_SWAP(endian); | ||
1007 | view->tex_resource_words[3] = 0; | ||
1008 | /* | ||
1009 | * in theory dword 4 is for number of elements, for use with resinfo, | ||
1010 | * but it seems to utterly fail to work, the amd gpu shader analyser | ||
1011 | * uses a const buffer to store the element sizes for buffer txq | ||
1012 | */ | ||
1013 | view->tex_resource_words[4] = 0; | ||
1014 | view->tex_resource_words[5] = 0; | ||
1015 | view->tex_resource_words[6] = S_038018_TYPE(V_038010_SQ_TEX_VTX_VALID_BUFFER); | ||
1016 | return &view->base; | ||
1017 | } | ||
1018 | |||
979 | struct pipe_sampler_view * | 1019 | struct pipe_sampler_view * |
980 | r600_create_sampler_view_custom(struct pipe_context *ctx, | 1020 | r600_create_sampler_view_custom(struct pipe_context *ctx, |
981 | struct pipe_resource *texture, | 1021 | struct pipe_resource *texture, |
@@ -1000,6 +1040,9 @@ r600_create_sampler_view_custom(struct pipe_context *ctx, | |||
1000 | view->base.reference.count = 1; | 1040 | view->base.reference.count = 1; |
1001 | view->base.context = ctx; | 1041 | view->base.context = ctx; |
1002 | 1042 | ||
1043 | if (texture->target == PIPE_BUFFER) | ||
1044 | return texture_buffer_sampler_view(view, texture->width0, 1); | ||
1045 | |||
1003 | swizzle[0] = state->swizzle_r; | 1046 | swizzle[0] = state->swizzle_r; |
1004 | swizzle[1] = state->swizzle_g; | 1047 | swizzle[1] = state->swizzle_g; |
1005 | swizzle[2] = state->swizzle_b; | 1048 | swizzle[2] = state->swizzle_b; |
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 3b61413f84e..34977373d21 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c | |||
@@ -588,19 +588,20 @@ static void r600_set_sampler_views(struct pipe_context *pipe, unsigned shader, | |||
588 | struct r600_texture *rtex = | 588 | struct r600_texture *rtex = |
589 | (struct r600_texture*)rviews[i]->base.texture; | 589 | (struct r600_texture*)rviews[i]->base.texture; |
590 | 590 | ||
591 | if (rtex->is_depth && !rtex->is_flushing_texture) { | 591 | if (rviews[i]->base.texture->target != PIPE_BUFFER) { |
592 | dst->views.compressed_depthtex_mask |= 1 << i; | 592 | if (rtex->is_depth && !rtex->is_flushing_texture) { |
593 | } else { | 593 | dst->views.compressed_depthtex_mask |= 1 << i; |
594 | dst->views.compressed_depthtex_mask &= ~(1 << i); | 594 | } else { |
595 | } | 595 | dst->views.compressed_depthtex_mask &= ~(1 << i); |
596 | } | ||
596 | 597 | ||
597 | /* Track compressed colorbuffers. */ | 598 | /* Track compressed colorbuffers. */ |
598 | if (rtex->cmask_size && rtex->fmask_size) { | 599 | if (rtex->cmask_size && rtex->fmask_size) { |
599 | dst->views.compressed_colortex_mask |= 1 << i; | 600 | dst->views.compressed_colortex_mask |= 1 << i; |
600 | } else { | 601 | } else { |
601 | dst->views.compressed_colortex_mask &= ~(1 << i); | 602 | dst->views.compressed_colortex_mask &= ~(1 << i); |
603 | } | ||
602 | } | 604 | } |
603 | |||
604 | /* Changing from array to non-arrays textures and vice versa requires | 605 | /* Changing from array to non-arrays textures and vice versa requires |
605 | * updating TEX_ARRAY_OVERRIDE in sampler states on R6xx-R7xx. */ | 606 | * updating TEX_ARRAY_OVERRIDE in sampler states on R6xx-R7xx. */ |
606 | if (rctx->chip_class <= R700 && | 607 | if (rctx->chip_class <= R700 && |
@@ -625,6 +626,7 @@ static void r600_set_sampler_views(struct pipe_context *pipe, unsigned shader, | |||
625 | dst->views.compressed_depthtex_mask &= dst->views.enabled_mask; | 626 | dst->views.compressed_depthtex_mask &= dst->views.enabled_mask; |
626 | dst->views.compressed_colortex_mask &= dst->views.enabled_mask; | 627 | dst->views.compressed_colortex_mask &= dst->views.enabled_mask; |
627 | dst->views.dirty_txq_constants = TRUE; | 628 | dst->views.dirty_txq_constants = TRUE; |
629 | dst->views.dirty_buffer_constants = TRUE; | ||
628 | r600_sampler_views_dirty(rctx, &dst->views); | 630 | r600_sampler_views_dirty(rctx, &dst->views); |
629 | 631 | ||
630 | if (dirty_sampler_states_mask) { | 632 | if (dirty_sampler_states_mask) { |
@@ -1023,6 +1025,92 @@ static void r600_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask | |||
1023 | rctx->sample_mask.atom.dirty = true; | 1025 | rctx->sample_mask.atom.dirty = true; |
1024 | } | 1026 | } |
1025 | 1027 | ||
1028 | /* | ||
1029 | * On r600/700 hw we don't have vertex fetch swizzle, though TBO | ||
1030 | * doesn't require full swizzles it does need masking and setting alpha | ||
1031 | * to one, so we setup a set of 5 constants with the masks + alpha value | ||
1032 | * then in the shader, we AND the 4 components with 0xffffffff or 0, | ||
1033 | * then OR the alpha with the value given here. | ||
1034 | * We use a 6th constant to store the txq buffer size in | ||
1035 | */ | ||
1036 | static void r600_setup_buffer_constants(struct r600_context *rctx, int shader_type) | ||
1037 | { | ||
1038 | struct r600_textures_info *samplers = &rctx->samplers[shader_type]; | ||
1039 | int bits; | ||
1040 | uint32_t array_size; | ||
1041 | struct pipe_constant_buffer cb; | ||
1042 | int i, j; | ||
1043 | |||
1044 | if (!samplers->views.dirty_buffer_constants) | ||
1045 | return; | ||
1046 | |||
1047 | samplers->views.dirty_buffer_constants = FALSE; | ||
1048 | |||
1049 | bits = util_last_bit(samplers->views.enabled_mask); | ||
1050 | array_size = bits * 8 * sizeof(uint32_t) * 4; | ||
1051 | samplers->buffer_constants = realloc(samplers->buffer_constants, array_size); | ||
1052 | memset(samplers->buffer_constants, 0, array_size); | ||
1053 | for (i = 0; i < bits; i++) { | ||
1054 | if (samplers->views.enabled_mask & (1 << i)) { | ||
1055 | int offset = i * 8; | ||
1056 | const struct util_format_description *desc; | ||
1057 | desc = util_format_description(samplers->views.views[i]->base.format); | ||
1058 | |||
1059 | for (j = 0; j < 4; j++) | ||
1060 | if (j < desc->nr_channels) | ||
1061 | samplers->buffer_constants[offset+j] = 0xffffffff; | ||
1062 | else | ||
1063 | samplers->buffer_constants[offset+j] = 0x0; | ||
1064 | if (desc->nr_channels < 4) { | ||
1065 | if (desc->channel[0].pure_integer) | ||
1066 | samplers->buffer_constants[offset+4] = 1; | ||
1067 | else | ||
1068 | samplers->buffer_constants[offset+4] = 0x3f800000; | ||
1069 | } else | ||
1070 | samplers->buffer_constants[offset + 4] = 0; | ||
1071 | |||
1072 | samplers->buffer_constants[offset + 5] = samplers->views.views[i]->base.texture->width0 / util_format_get_blocksize(samplers->views.views[i]->base.format); | ||
1073 | } | ||
1074 | } | ||
1075 | |||
1076 | cb.buffer = NULL; | ||
1077 | cb.user_buffer = samplers->buffer_constants; | ||
1078 | cb.buffer_offset = 0; | ||
1079 | cb.buffer_size = array_size; | ||
1080 | rctx->context.set_constant_buffer(&rctx->context, shader_type, R600_BUFFER_INFO_CONST_BUFFER, &cb); | ||
1081 | pipe_resource_reference(&cb.buffer, NULL); | ||
1082 | } | ||
1083 | |||
1084 | /* On evergreen we only need to store the buffer size for TXQ */ | ||
1085 | static void eg_setup_buffer_constants(struct r600_context *rctx, int shader_type) | ||
1086 | { | ||
1087 | struct r600_textures_info *samplers = &rctx->samplers[shader_type]; | ||
1088 | int bits; | ||
1089 | uint32_t array_size; | ||
1090 | struct pipe_constant_buffer cb; | ||
1091 | int i; | ||
1092 | |||
1093 | if (!samplers->views.dirty_buffer_constants) | ||
1094 | return; | ||
1095 | |||
1096 | samplers->views.dirty_buffer_constants = FALSE; | ||
1097 | |||
1098 | bits = util_last_bit(samplers->views.enabled_mask); | ||
1099 | array_size = bits * sizeof(uint32_t) * 4; | ||
1100 | samplers->buffer_constants = realloc(samplers->buffer_constants, array_size); | ||
1101 | memset(samplers->buffer_constants, 0, array_size); | ||
1102 | for (i = 0; i < bits; i++) | ||
1103 | if (samplers->views.enabled_mask & (1 << i)) | ||
1104 | samplers->buffer_constants[i] = samplers->views.views[i]->base.texture->width0 / util_format_get_blocksize(samplers->views.views[i]->base.format); | ||
1105 | |||
1106 | cb.buffer = NULL; | ||
1107 | cb.user_buffer = samplers->buffer_constants; | ||
1108 | cb.buffer_offset = 0; | ||
1109 | cb.buffer_size = array_size; | ||
1110 | rctx->context.set_constant_buffer(&rctx->context, shader_type, R600_BUFFER_INFO_CONST_BUFFER, &cb); | ||
1111 | pipe_resource_reference(&cb.buffer, NULL); | ||
1112 | } | ||
1113 | |||
1026 | static void r600_setup_txq_cube_array_constants(struct r600_context *rctx, int shader_type) | 1114 | static void r600_setup_txq_cube_array_constants(struct r600_context *rctx, int shader_type) |
1027 | { | 1115 | { |
1028 | struct r600_textures_info *samplers = &rctx->samplers[shader_type]; | 1116 | struct r600_textures_info *samplers = &rctx->samplers[shader_type]; |
@@ -1090,6 +1178,21 @@ static bool r600_update_derived_state(struct r600_context *rctx) | |||
1090 | if (ps_dirty) | 1178 | if (ps_dirty) |
1091 | r600_context_pipe_state_set(rctx, &rctx->ps_shader->current->rstate); | 1179 | r600_context_pipe_state_set(rctx, &rctx->ps_shader->current->rstate); |
1092 | 1180 | ||
1181 | /* on R600 we stuff masks + txq info into one constant buffer */ | ||
1182 | /* on evergreen we only need a txq info one */ | ||
1183 | if (rctx->chip_class < EVERGREEN) { | ||
1184 | if (rctx->ps_shader && rctx->ps_shader->current->shader.uses_tex_buffers) | ||
1185 | r600_setup_buffer_constants(rctx, PIPE_SHADER_FRAGMENT); | ||
1186 | if (rctx->vs_shader && rctx->vs_shader->current->shader.uses_tex_buffers) | ||
1187 | r600_setup_buffer_constants(rctx, PIPE_SHADER_VERTEX); | ||
1188 | } else { | ||
1189 | if (rctx->ps_shader && rctx->ps_shader->current->shader.uses_tex_buffers) | ||
1190 | eg_setup_buffer_constants(rctx, PIPE_SHADER_FRAGMENT); | ||
1191 | if (rctx->vs_shader && rctx->vs_shader->current->shader.uses_tex_buffers) | ||
1192 | eg_setup_buffer_constants(rctx, PIPE_SHADER_VERTEX); | ||
1193 | } | ||
1194 | |||
1195 | |||
1093 | if (rctx->ps_shader && rctx->ps_shader->current->shader.has_txq_cube_array_z_comp) | 1196 | if (rctx->ps_shader && rctx->ps_shader->current->shader.has_txq_cube_array_z_comp) |
1094 | r600_setup_txq_cube_array_constants(rctx, PIPE_SHADER_FRAGMENT); | 1197 | r600_setup_txq_cube_array_constants(rctx, PIPE_SHADER_FRAGMENT); |
1095 | if (rctx->vs_shader && rctx->vs_shader->current->shader.has_txq_cube_array_z_comp) | 1198 | if (rctx->vs_shader && rctx->vs_shader->current->shader.has_txq_cube_array_z_comp) |
diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index 85da0930242..45a30f85df4 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c | |||
@@ -912,18 +912,26 @@ void r600_init_surface_functions(struct r600_context *r600) | |||
912 | r600->context.surface_destroy = r600_surface_destroy; | 912 | r600->context.surface_destroy = r600_surface_destroy; |
913 | } | 913 | } |
914 | 914 | ||
915 | static unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format, | 915 | unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format, |
916 | const unsigned char *swizzle_view) | 916 | const unsigned char *swizzle_view, |
917 | boolean vtx) | ||
917 | { | 918 | { |
918 | unsigned i; | 919 | unsigned i; |
919 | unsigned char swizzle[4]; | 920 | unsigned char swizzle[4]; |
920 | unsigned result = 0; | 921 | unsigned result = 0; |
921 | const uint32_t swizzle_shift[4] = { | 922 | const uint32_t tex_swizzle_shift[4] = { |
922 | 16, 19, 22, 25, | 923 | 16, 19, 22, 25, |
923 | }; | 924 | }; |
925 | const uint32_t vtx_swizzle_shift[4] = { | ||
926 | 3, 6, 9, 12, | ||
927 | }; | ||
924 | const uint32_t swizzle_bit[4] = { | 928 | const uint32_t swizzle_bit[4] = { |
925 | 0, 1, 2, 3, | 929 | 0, 1, 2, 3, |
926 | }; | 930 | }; |
931 | const uint32_t *swizzle_shift = tex_swizzle_shift; | ||
932 | |||
933 | if (vtx) | ||
934 | swizzle_shift = vtx_swizzle_shift; | ||
927 | 935 | ||
928 | if (swizzle_view) { | 936 | if (swizzle_view) { |
929 | util_format_compose_swizzles(swizzle_format, swizzle_view, swizzle); | 937 | util_format_compose_swizzles(swizzle_format, swizzle_view, swizzle); |
@@ -977,7 +985,7 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen, | |||
977 | }; | 985 | }; |
978 | desc = util_format_description(format); | 986 | desc = util_format_description(format); |
979 | 987 | ||
980 | word4 |= r600_get_swizzle_combined(desc->swizzle, swizzle_view); | 988 | word4 |= r600_get_swizzle_combined(desc->swizzle, swizzle_view, FALSE); |
981 | 989 | ||
982 | /* Colorspace (return non-RGB formats directly). */ | 990 | /* Colorspace (return non-RGB formats directly). */ |
983 | switch (desc->colorspace) { | 991 | switch (desc->colorspace) { |