Making texture fetching split from samplers.

This commit is contained in:
Ben Vanik 2014-01-20 15:36:33 -08:00
parent af223b2067
commit 4de33a6e2d
4 changed files with 177 additions and 96 deletions

View File

@ -56,15 +56,44 @@ D3D11GraphicsDriver::D3D11GraphicsDriver(
buffer_desc.ByteWidth = (32) * sizeof(int);
hr = device_->CreateBuffer(
&buffer_desc, NULL, &state_.constant_buffers.gs_consts);
// TODO(benvanik): pattern?
invalid_texture_view_ = NULL;
D3D11_SAMPLER_DESC sampler_desc;
xe_zero_struct(&sampler_desc, sizeof(sampler_desc));
sampler_desc.Filter;
sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
sampler_desc.MipLODBias;
sampler_desc.MaxAnisotropy = 1;
sampler_desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
sampler_desc.BorderColor[0];
sampler_desc.BorderColor[1];
sampler_desc.BorderColor[2];
sampler_desc.BorderColor[3];
sampler_desc.MinLOD;
sampler_desc.MaxLOD;
hr = device_->CreateSamplerState(
&sampler_desc, &invalid_texture_sampler_state_);
if (FAILED(hr)) {
XEFATAL("D3D11: unable to create invalid sampler state");
}
}
D3D11GraphicsDriver::~D3D11GraphicsDriver() {
RebuildRenderTargets(0, 0);
for (size_t n = 0; n < XECOUNT(state_.texture_fetchers); n++) {
XESAFERELEASE(state_.texture_fetchers[n].view);
}
XESAFERELEASE(state_.constant_buffers.float_constants);
XESAFERELEASE(state_.constant_buffers.bool_constants);
XESAFERELEASE(state_.constant_buffers.loop_constants);
XESAFERELEASE(state_.constant_buffers.vs_consts);
XESAFERELEASE(state_.constant_buffers.gs_consts);
XESAFERELEASE(invalid_texture_view_);
XESAFERELEASE(invalid_texture_sampler_state_);
delete shader_cache_;
XESAFERELEASE(context_);
XESAFERELEASE(device_);
@ -119,6 +148,13 @@ void D3D11GraphicsDriver::SetShader(
int D3D11GraphicsDriver::SetupDraw(XE_GPU_PRIMITIVE_TYPE prim_type) {
RegisterFile& rf = register_file_;
// Ignore copies.
uint32_t enable_mode = rf.values[XE_GPU_REG_RB_MODECONTROL].u32 & 0x7;
if (enable_mode != 4) {
XELOGW("D3D11: ignoring draw with enable mode %d", enable_mode);
return 1;
}
uint32_t state_overrides = 0;
if (prim_type == XE_GPU_PRIMITIVE_TYPE_RECTANGLE_LIST) {
// Rect lists aren't culled. There may be other things they skip too.
@ -681,7 +717,7 @@ int D3D11GraphicsDriver::UpdateState(uint32_t state_overrides) {
}
ID3D11BlendState* blend_state = 0;
device_->CreateBlendState(&blend_desc, &blend_state);
context_->OMSetBlendState(blend_state, blend_factor, sample_mask);
//context_->OMSetBlendState(blend_state, blend_factor, sample_mask);
XESAFERELEASE(blend_state);
return 0;
@ -823,22 +859,28 @@ int D3D11GraphicsDriver::PrepareFetchers() {
}
}
// Vertex texture inputs.
// All texture inputs.
if (PrepareTextureFetchers()) {
XELOGE("D3D11: unable to prepare texture fetchers");
return 1;
}
// Vertex texture samplers.
auto tex_inputs = state_.vertex_shader->GetTextureBufferInputs();
for (size_t n = 0; n < tex_inputs->count; n++) {
auto input = tex_inputs->descs[n];
if (PrepareTextureFetcher(XE_GPU_SHADER_TYPE_VERTEX, input)) {
if (PrepareTextureSampler(XE_GPU_SHADER_TYPE_VERTEX, input)) {
XELOGE("D3D11: unable to prepare texture buffer");
return 1;
}
}
// Pixel shader texture inputs.
// Pixel shader texture sampler.
XEASSERTNOTNULL(state_.pixel_shader);
tex_inputs = state_.pixel_shader->GetTextureBufferInputs();
for (size_t n = 0; n < tex_inputs->count; n++) {
auto input = tex_inputs->descs[n];
if (PrepareTextureFetcher(XE_GPU_SHADER_TYPE_PIXEL, input)) {
if (PrepareTextureSampler(XE_GPU_SHADER_TYPE_PIXEL, input)) {
XELOGE("D3D11: unable to prepare texture buffer");
return 1;
}
@ -922,6 +964,95 @@ int D3D11GraphicsDriver::PrepareVertexBuffer(Shader::vtx_buffer_desc_t& desc) {
return 0;
}
int D3D11GraphicsDriver::PrepareTextureFetchers() {
RegisterFile& rf = register_file_;
for (int n = 0; n < XECOUNT(state_.texture_fetchers); n++) {
auto& fetcher = state_.texture_fetchers[n];
// TODO(benvanik): caching.
fetcher.enabled = false;
XESAFERELEASE(fetcher.view);
fetcher.view = NULL;
int r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + n * 6;
xe_gpu_fetch_group_t* group = (xe_gpu_fetch_group_t*)&rf.values[r];
auto& fetch = group->texture_fetch;
if (fetch.type != 0x2) {
continue;
}
fetcher.info = GetTextureInfo(fetch);
if (fetcher.info.format == DXGI_FORMAT_UNKNOWN) {
XELOGW("D3D11: unknown texture format %d", fetch.format);
continue;
}
D3D11_SHADER_RESOURCE_VIEW_DESC texture_view_desc;
xe_zero_struct(&texture_view_desc, sizeof(texture_view_desc));
// TODO(benvanik): this may need to be typed on the fetch instruction (float/int/etc?)
texture_view_desc.Format = fetcher.info.format;
ID3D11Resource* texture = NULL;
D3D_SRV_DIMENSION dimension = D3D11_SRV_DIMENSION_UNKNOWN;
switch (fetch.dimension) {
case DIMENSION_1D:
texture_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
texture_view_desc.Texture1D.MipLevels = 1;
texture_view_desc.Texture1D.MostDetailedMip = 0;
if (FetchTexture1D(fetch, fetcher.info, &texture)) {
XELOGE("D3D11: failed to fetch Texture1D");
return 1;
}
break;
case DIMENSION_2D:
texture_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
texture_view_desc.Texture2D.MipLevels = 1;
texture_view_desc.Texture2D.MostDetailedMip = 0;
if (FetchTexture2D(fetch, fetcher.info, &texture)) {
XELOGE("D3D11: failed to fetch Texture2D");
return 1;
}
break;
case DIMENSION_3D:
texture_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
texture_view_desc.Texture3D.MipLevels = 1;
texture_view_desc.Texture3D.MostDetailedMip = 0;
if (FetchTexture3D(fetch, fetcher.info, &texture)) {
XELOGE("D3D11: failed to fetch Texture3D");
return 1;
}
break;
case DIMENSION_CUBE:
texture_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
texture_view_desc.TextureCube.MipLevels = 1;
texture_view_desc.TextureCube.MostDetailedMip = 0;
if (FetchTextureCube(fetch, fetcher.info, &texture)) {
XELOGE("D3D11: failed to fetch TextureCube");
return 1;
}
break;
}
XEASSERTNOTNULL(texture);
ID3D11ShaderResourceView* texture_view = NULL;
HRESULT hr = device_->CreateShaderResourceView(
texture, &texture_view_desc, &texture_view);
if (FAILED(hr)) {
XELOGE("D3D11: unable to create texture resource view");
texture->Release();
return 1;
}
texture->Release();
fetcher.enabled = true;
fetcher.view = texture_view;
}
return 0;
}
D3D11GraphicsDriver::TextureInfo D3D11GraphicsDriver::GetTextureInfo(
xe_gpu_texture_fetch_t& fetch) {
// a2xx_sq_surfaceformat
@ -933,6 +1064,9 @@ D3D11GraphicsDriver::TextureInfo D3D11GraphicsDriver::GetTextureInfo(
case FMT_8_8_8_8:
info.format = DXGI_FORMAT_R8G8B8A8_UNORM;
break;
case FMT_4_4_4_4:
info.format = DXGI_FORMAT_B4G4R4A4_UNORM;
break;
case FMT_1_REVERSE:
case FMT_1:
case FMT_8:
@ -947,7 +1081,6 @@ D3D11GraphicsDriver::TextureInfo D3D11GraphicsDriver::GetTextureInfo(
case FMT_Y1_Cr_Y0_Cb:
case FMT_5_5_5_1:
case FMT_8_8_8_8_A:
case FMT_4_4_4_4:
case FMT_10_11_11:
case FMT_11_11_10:
case FMT_DXT1:
@ -1000,7 +1133,6 @@ D3D11GraphicsDriver::TextureInfo D3D11GraphicsDriver::GetTextureInfo(
}
int D3D11GraphicsDriver::FetchTexture1D(
Shader::tex_buffer_desc_t& desc,
xe_gpu_texture_fetch_t& fetch,
TextureInfo& info,
ID3D11Resource** out_texture) {
@ -1028,7 +1160,6 @@ int D3D11GraphicsDriver::FetchTexture1D(
}
int D3D11GraphicsDriver::FetchTexture2D(
Shader::tex_buffer_desc_t& desc,
xe_gpu_texture_fetch_t& fetch,
TextureInfo& info,
ID3D11Resource** out_texture) {
@ -1079,7 +1210,6 @@ int D3D11GraphicsDriver::FetchTexture2D(
}
int D3D11GraphicsDriver::FetchTexture3D(
Shader::tex_buffer_desc_t& desc,
xe_gpu_texture_fetch_t& fetch,
TextureInfo& info,
ID3D11Resource** out_texture) {
@ -1102,7 +1232,6 @@ int D3D11GraphicsDriver::FetchTexture3D(
}
int D3D11GraphicsDriver::FetchTextureCube(
Shader::tex_buffer_desc_t& desc,
xe_gpu_texture_fetch_t& fetch,
TextureInfo& info,
ID3D11Resource** out_texture) {
@ -1111,89 +1240,35 @@ int D3D11GraphicsDriver::FetchTextureCube(
return 1;
}
int D3D11GraphicsDriver::PrepareTextureFetcher(
int D3D11GraphicsDriver::PrepareTextureSampler(
xenos::XE_GPU_SHADER_TYPE shader_type, Shader::tex_buffer_desc_t& desc) {
RegisterFile& rf = register_file_;
int r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + desc.fetch_slot * 6;
xe_gpu_fetch_group_t* group = (xe_gpu_fetch_group_t*)&rf.values[r];
auto& fetch = group->texture_fetch;
// If this assert doesn't hold, maybe we just abort?
if (fetch.type != 0x2) {
XELOGW("D3D11: texture fetcher pointed at a vertex group?");
return 1;
}
TextureInfo info = GetTextureInfo(fetch);
if (info.format == DXGI_FORMAT_UNKNOWN) {
XELOGE("D3D11: unrecognized texture format %d", fetch.format);
return 1;
auto& fetcher = state_.texture_fetchers[desc.fetch_slot];
auto& info = fetcher.info;
if (!fetcher.enabled ||
info.format == DXGI_FORMAT_UNKNOWN) {
XELOGW("D3D11: ignoring texture fetch: disabled or an unknown format");
if (shader_type == XE_GPU_SHADER_TYPE_VERTEX) {
context_->VSSetShaderResources(desc.input_index,
1, &invalid_texture_view_);
context_->VSSetSamplers(desc.input_index,
1, &invalid_texture_sampler_state_);
} else {
context_->PSSetShaderResources(desc.input_index,
1, &invalid_texture_view_);
context_->PSSetSamplers(desc.input_index,
1, &invalid_texture_sampler_state_);
}
return 0;
}
HRESULT hr;
D3D11_SHADER_RESOURCE_VIEW_DESC texture_view_desc;
xe_zero_struct(&texture_view_desc, sizeof(texture_view_desc));
// TODO(benvanik): this may need to be typed on the fetch instruction (float/int/etc?)
texture_view_desc.Format = info.format;
ID3D11Resource* texture = NULL;
D3D_SRV_DIMENSION dimension = D3D11_SRV_DIMENSION_UNKNOWN;
switch (desc.tex_fetch.dimension) {
case DIMENSION_1D:
texture_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
texture_view_desc.Texture1D.MipLevels = 1;
texture_view_desc.Texture1D.MostDetailedMip = 0;
if (FetchTexture1D(desc, fetch, info, &texture)) {
XELOGE("D3D11: failed to fetch Texture1D");
return 1;
}
break;
case DIMENSION_2D:
texture_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
texture_view_desc.Texture2D.MipLevels = 1;
texture_view_desc.Texture2D.MostDetailedMip = 0;
if (FetchTexture2D(desc, fetch, info, &texture)) {
XELOGE("D3D11: failed to fetch Texture2D");
return 1;
}
break;
case DIMENSION_3D:
texture_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
texture_view_desc.Texture3D.MipLevels = 1;
texture_view_desc.Texture3D.MostDetailedMip = 0;
if (FetchTexture3D(desc, fetch, info, &texture)) {
XELOGE("D3D11: failed to fetch Texture3D");
return 1;
}
break;
case DIMENSION_CUBE:
texture_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
texture_view_desc.TextureCube.MipLevels = 1;
texture_view_desc.TextureCube.MostDetailedMip = 0;
if (FetchTextureCube(desc, fetch, info, &texture)) {
XELOGE("D3D11: failed to fetch TextureCube");
return 1;
}
break;
}
XEASSERTNOTNULL(texture);
ID3D11ShaderResourceView* texture_view = NULL;
hr = device_->CreateShaderResourceView(
texture, &texture_view_desc, &texture_view);
if (FAILED(hr)) {
XELOGE("D3D11: unable to create texture resource view");
texture->Release();
return 1;
}
if (shader_type == XE_GPU_SHADER_TYPE_VERTEX) {
context_->VSSetShaderResources(desc.input_index, 1, &texture_view);
context_->VSSetShaderResources(desc.input_index, 1, &fetcher.view);
} else {
context_->PSSetShaderResources(desc.input_index, 1, &texture_view);
context_->PSSetShaderResources(desc.input_index, 1, &fetcher.view);
}
texture_view->Release();
texture->Release();
D3D11_SAMPLER_DESC sampler_desc;
xe_zero_struct(&sampler_desc, sizeof(sampler_desc));
@ -1213,7 +1288,7 @@ int D3D11GraphicsDriver::PrepareTextureFetcher(
ID3D11SamplerState* sampler_state = NULL;
hr = device_->CreateSamplerState(&sampler_desc, &sampler_state);
if (FAILED(hr)) {
XELOGE("D3D11:: unable to create sampler state");
XELOGE("D3D11: unable to create sampler state");
return 1;
}
if (shader_type == XE_GPU_SHADER_TYPE_VERTEX) {

View File

@ -63,7 +63,8 @@ private:
int BindShaders();
int PrepareFetchers();
int PrepareVertexBuffer(Shader::vtx_buffer_desc_t& desc);
int PrepareTextureFetcher(xenos::XE_GPU_SHADER_TYPE shader_type,
int PrepareTextureFetchers();
int PrepareTextureSampler(xenos::XE_GPU_SHADER_TYPE shader_type,
Shader::tex_buffer_desc_t& desc);
typedef struct {
DXGI_FORMAT format;
@ -71,20 +72,16 @@ private:
uint32_t block_height;
} TextureInfo;
TextureInfo GetTextureInfo(xenos::xe_gpu_texture_fetch_t& fetch);
int FetchTexture1D(Shader::tex_buffer_desc_t& desc,
xenos::xe_gpu_texture_fetch_t& fetch,
int FetchTexture1D(xenos::xe_gpu_texture_fetch_t& fetch,
TextureInfo& info,
ID3D11Resource** out_texture);
int FetchTexture2D(Shader::tex_buffer_desc_t& desc,
xenos::xe_gpu_texture_fetch_t& fetch,
int FetchTexture2D(xenos::xe_gpu_texture_fetch_t& fetch,
TextureInfo& info,
ID3D11Resource** out_texture);
int FetchTexture3D(Shader::tex_buffer_desc_t& desc,
xenos::xe_gpu_texture_fetch_t& fetch,
int FetchTexture3D(xenos::xe_gpu_texture_fetch_t& fetch,
TextureInfo& info,
ID3D11Resource** out_texture);
int FetchTextureCube(Shader::tex_buffer_desc_t& desc,
xenos::xe_gpu_texture_fetch_t& fetch,
int FetchTextureCube(xenos::xe_gpu_texture_fetch_t& fetch,
TextureInfo& info,
ID3D11Resource** out_texture);
int PrepareIndexBuffer(
@ -97,6 +94,9 @@ private:
ID3D11DeviceContext* context_;
D3D11ShaderCache* shader_cache_;
ID3D11ShaderResourceView* invalid_texture_view_;
ID3D11SamplerState* invalid_texture_sampler_state_;
struct {
uint32_t width;
uint32_t height;
@ -120,6 +120,12 @@ private:
ID3D11Buffer* vs_consts;
ID3D11Buffer* gs_consts;
} constant_buffers;
struct {
bool enabled;
TextureInfo info;
ID3D11ShaderResourceView* view;
} texture_fetchers[32];
} state_;
enum StateOverrides {

View File

@ -255,7 +255,7 @@ void Shader::GatherTextureFetch(const xenos::instr_fetch_tex_t* tex) {
XEASSERT(inputs.count + 1 < XECOUNT(inputs.descs));
auto& input = inputs.descs[inputs.count++];
input.input_index = inputs.count - 1;
input.fetch_slot = tex->const_idx - 16; // ?
input.fetch_slot = tex->const_idx & 0xF; // ?
input.tex_fetch = *tex;
// Format mangling, size estimation, etc.

View File

@ -61,7 +61,7 @@ public:
} tex_buffer_desc_t;
typedef struct {
uint32_t count;
tex_buffer_desc_t descs[16];
tex_buffer_desc_t descs[32];
} tex_buffer_inputs_t;
const tex_buffer_inputs_t* GetTextureBufferInputs();